/[svn]/linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceArts.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceArts.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3766 - (show annotations) (download)
Mon Apr 6 12:41:49 2020 UTC (3 years, 11 months ago) by schoenebeck
File size: 8097 byte(s)
Fixed deadlocks (e.g. when restarting engines).

* Individual thread implementations (e.g. disk thread, etc.):
  Disable thread cancellation on critical sections, e.g. when holding
  mutex locks, to prevent deadlocks if thread is stopped and/or
  restarted.

* Added TestCancel() calls to thread implementations if missing.

* No need to wrap Thread::TestCancel() calls into
  CONFIG_PTHREAD_TESTCANCEL macro conditions (since TestCancel() is
  already a stub on systems which don't have pthread_testcancel()
  available).

* If compiled for debugging: give each thread a human readable name
  to simplify debugging of multi-threading issues.

* DiskThreadBase: TestCancel() and pthread_testcancel() calls are
  per-se redundant, so only call TestCancel().

* Added missing override keywords to silent compiler warnings.

* Bumped version (2.1.1.svn54).

1 /***************************************************************************
2 * *
3 * Copyright (C) 2006 - 2020 Christian Schoenebeck *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This library is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this library; if not, write to the Free Software *
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18 * MA 02111-1307 USA *
19 ***************************************************************************/
20
21 #include "AudioOutputDeviceArts.h"
22 #include "AudioOutputDeviceFactory.h"
23
24 //TODO: this driver currently allows and expects only a bit depth of 16 !
25 #define LS_ARTS_BITDEPTH 16
26
27 namespace LinuxSampler {
28
29 /// number of currently existing aRts audio output devices in LinuxSampler
30 static int existingArtsDevices = 0;
31
32
33
34 // *************** ParameterName ***************
35 // *
36
37 AudioOutputDeviceArts::ParameterName::ParameterName() : DeviceCreationParameterString() {
38 InitWithDefault(); // use default name
39 }
40
41 AudioOutputDeviceArts::ParameterName::ParameterName(String s) throw (Exception) : DeviceCreationParameterString(s) {
42 }
43
44 String AudioOutputDeviceArts::ParameterName::Description() {
45 return "Arbitrary aRts client name";
46 }
47
48 bool AudioOutputDeviceArts::ParameterName::Fix() {
49 return true;
50 }
51
52 bool AudioOutputDeviceArts::ParameterName::Mandatory() {
53 return false;
54 }
55
56 std::map<String,DeviceCreationParameter*> AudioOutputDeviceArts::ParameterName::DependsAsParameters() {
57 return std::map<String,DeviceCreationParameter*>(); // no dependencies
58 }
59
60 std::vector<String> AudioOutputDeviceArts::ParameterName::PossibilitiesAsString(std::map<String,String> Parameters) {
61 return std::vector<String>();
62 }
63
64 optional<String> AudioOutputDeviceArts::ParameterName::DefaultAsString(std::map<String,String> Parameters) {
65 return (existingArtsDevices) ? "LinuxSampler" + ToString(existingArtsDevices) : "LinuxSampler";
66 }
67
68 void AudioOutputDeviceArts::ParameterName::OnSetValue(String s) throw (Exception) {
69 // not possible, as parameter is fix
70 }
71
72 String AudioOutputDeviceArts::ParameterName::Name() {
73 return "NAME";
74 }
75
76
77
78 // *************** AudioOutputDeviceArts ***************
79 // *
80
81 /**
82 * Create and initialize aRts audio output device with given parameters.
83 *
84 * @param Parameters - optional parameters
85 * @throws AudioOutputException if output device cannot be opened
86 */
87 AudioOutputDeviceArts::AudioOutputDeviceArts(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) {
88 uiArtsChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
89 uiSampleRate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
90 String name = ((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString();
91
92 int res;
93
94 // initialize the aRts API in case there is no aRts audio output device yet
95 if (!existingArtsDevices) {
96 res = arts_init();
97 if (res) throw AudioOutputException(String("arts_init() failed (err ") + ToString(res) + ")");
98 }
99 existingArtsDevices++;
100
101 hStream = arts_play_stream(uiSampleRate, LS_ARTS_BITDEPTH, uiArtsChannels, name.c_str());
102 uiPacketSize = arts_stream_get(hStream, ARTS_P_PACKET_SIZE);
103 FragmentSize = uiPacketSize / (LS_ARTS_BITDEPTH / 8 * uiArtsChannels);
104
105 // create aRts audio output buffer
106 pArtsOutputBuffer = new int16_t[uiPacketSize / (LS_ARTS_BITDEPTH / 8)];
107
108 // create audio channels for this audio device to which the sampler engines can write to
109 for (int i = 0; i < uiArtsChannels; i++)
110 this->Channels.push_back(new AudioChannel(i, FragmentSize));
111
112 // finally activate device if desired
113 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) Play();
114 }
115
116 AudioOutputDeviceArts::~AudioOutputDeviceArts() {
117 //dmsg(0,("Stopping aRts Thread..."));
118 //StopThread(); //FIXME: commented out due to a bug in thread.cpp (StopThread() doesn't return at all)
119 //dmsg(0,("OK\n"));
120 arts_close_stream(hStream);
121 existingArtsDevices--;
122 if (!existingArtsDevices) arts_free();
123 if (pArtsOutputBuffer) delete[] pArtsOutputBuffer;
124 }
125
126 void AudioOutputDeviceArts::Play() {
127 StartThread();
128 }
129
130 bool AudioOutputDeviceArts::IsPlaying() {
131 return IsRunning(); // if Thread is running
132 }
133
134 void AudioOutputDeviceArts::Stop() {
135 StopThread();
136 }
137
138 AudioChannel* AudioOutputDeviceArts::CreateChannel(uint ChannelNr) {
139 // just create a mix channel
140 return new AudioChannel(ChannelNr, Channel(ChannelNr % uiArtsChannels));
141 }
142
143 uint AudioOutputDeviceArts::MaxSamplesPerCycle() {
144 return FragmentSize;
145 }
146
147 uint AudioOutputDeviceArts::SampleRate() {
148 return uiSampleRate;
149 }
150
151 String AudioOutputDeviceArts::Name() {
152 return "ARTS";
153 }
154
155 String AudioOutputDeviceArts::Driver() {
156 return Name();
157 }
158
159 String AudioOutputDeviceArts::Description() {
160 return "Analog Realtime Synthesizer";
161 }
162
163 String AudioOutputDeviceArts::Version() {
164 String s = "$Revision$";
165 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
166 }
167
168 /**
169 * Entry point for the thread.
170 */
171 int AudioOutputDeviceArts::Main() {
172
173 #if DEBUG
174 Thread::setNameOfCaller("ArtsAudio");
175 #endif
176
177 while (true) {
178 TestCancel();
179
180 // prevent thread from being cancelled
181 // (e.g. to prevent deadlocks while holding mutex lock(s))
182 pushCancelable(false);
183
184 // let all connected engines render 'FragmentSize' sample points
185 RenderAudio(FragmentSize);
186
187 // convert from DSP value range (-1.0..+1.0) to 16 bit integer value
188 // range (-32768..+32767), check clipping and copy to aRts output buffer
189 for (int c = 0; c < uiArtsChannels; c++) {
190 float* in = Channels[c]->Buffer();
191 for (int i = 0, o = c; i < FragmentSize; i++ , o += uiArtsChannels) {
192 float sample_point = in[i] * 32768.0f;
193 if (sample_point < -32768.0) sample_point = -32768.0;
194 if (sample_point > 32767.0) sample_point = 32767.0;
195 pArtsOutputBuffer[o] = (int16_t) sample_point;
196 }
197 }
198
199 // output sound
200 int res = arts_write(hStream, pArtsOutputBuffer, uiPacketSize);
201 if (res <= 0) {
202 fprintf(stderr, "AudioOutputDeviceArts: Audio output error, exiting.\n");
203 exit(EXIT_FAILURE);
204 }
205
206 // now allow thread being cancelled again
207 // (since all mutexes are now unlocked)
208 popCancelable();
209 }
210 }
211
212 } // namespace LinuxSampler

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC