r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / cinelerra / audioodevice.C
blob4e3889abae6d7daf8adf631c3c061821df076a3e
1 #include "audiodevice.h"
2 #include "bctimer.h"
3 #include "clip.h"
4 #include "condition.h"
5 #include "mutex.h"
6 #include "playbackconfig.h"
7 #include "sema.h"
9 #include <string.h>
11 int AudioDevice::write_buffer(double **output, int samples)
13 // find free buffer to fill
14         if(interrupt) return 0;
15         arm_buffer(arm_buffer_num, output, samples);
16         arm_buffer_num++;
17         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
18         return 0;
21 int AudioDevice::set_last_buffer()
23         arm_lock[arm_buffer_num]->lock("AudioDevice::set_last_buffer");
24         last_buffer[arm_buffer_num] = 1;
25         play_lock[arm_buffer_num]->unlock();
28         arm_buffer_num++;
29         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
30         return 0;
34 // must run before threading once to allocate buffers
35 // must send maximum size buffer the first time or risk reallocation while threaded
36 int AudioDevice::arm_buffer(int buffer_num, 
37         double **output, 
38         int samples)
40         int bits;
41         int new_size;
43         int i, j;
44         int input_offset;
45         int output_offset;
46         int output_advance;
47         int channel, last_input_channel;
48         double sample;
49         int int_sample, int_sample2;
50         int dither_value;
51         int frame;
52         int device_channels = get_ochannels();
53         char *buffer_num_buffer;
54         double *buffer_in_channel;
56         bits = get_obits();
58         frame = device_channels * (bits / 8);
60         new_size = frame * samples;
62         if(interrupt) return 1;
64 // wait for buffer to become available for writing
65         arm_lock[buffer_num]->lock("AudioDevice::arm_buffer");
66         if(interrupt) return 1;
68         if(new_size > buffer_size[buffer_num])
69         {
70                 delete [] output_buffer[buffer_num];
71                 output_buffer[buffer_num] = new char[new_size];
72                 buffer_size[buffer_num] = new_size;
73         }
75         buffer_size[buffer_num] = new_size;
77         buffer_num_buffer = output_buffer[buffer_num];
78         bzero(buffer_num_buffer, new_size);
79         
80         last_input_channel = device_channels - 1;
81 // copy data
82 // intel byte order only to correspond with bits_to_fmt
84         for(channel = 0; channel < device_channels; channel++)
85         {
86                 buffer_in_channel = output[channel];
87                 switch(bits)
88                 {
89                         case 8:
90                                 output_advance = device_channels;
91                                 if(play_dither)
92                                 {
93                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
94                                         {
95                                                 sample = buffer_in_channel[input_offset];
96                                                 CLAMP(sample, -1, 1);
97                                                 sample *= 0x7fff;
98                                                 int_sample = (int)sample;
99                                                 dither_value = rand() % 255;
100                                                 int_sample -= dither_value;
101                                                 int_sample /= 0x100;
102                                                 buffer_num_buffer[output_offset] = int_sample;
103                                         }
104                                 }
105                                 else
106                                 {
107                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
108                                         {
109                                                 sample = buffer_in_channel[input_offset];
110                                                 CLAMP(sample, -1, 1);
111                                                 sample *= 0x7f;
112                                                 int_sample = (int)sample;
113                                                 buffer_num_buffer[output_offset] = int_sample;
114                                         }
115                                 }
116                                 break;
118                         case 16:
119                                 output_advance = device_channels * 2 - 1;
120                                 if(play_dither)
121                                 {
122                                         for(output_offset = channel * 2, input_offset = 0; 
123                                                 input_offset < samples; 
124                                                 output_offset += output_advance, input_offset++)
125                                         {
126                                                 sample = buffer_in_channel[input_offset];
127                                                 CLAMP(sample, -1, 1);
128                                                 sample *= 0x7fffff;
129                                                 int_sample = (int)sample;
130                                                 dither_value = rand() % 255;
131                                                 int_sample -= dither_value;
132                                                 int_sample /= 0x100;
133                                                 buffer_num_buffer[output_offset] = int_sample;
134                                         }
135                                 }
136                                 else
137                                 {
138                                         for(output_offset = channel * 2, input_offset = 0; 
139                                                 input_offset < samples; 
140                                                 output_offset += output_advance, input_offset++)
141                                         {
142                                                 sample = buffer_in_channel[input_offset];
143                                                 CLAMP(sample, -1, 1);
144                                                 sample *= 0x7fff;
145                                                 int_sample = (int)sample;
146                                                 buffer_num_buffer[output_offset++] = (int_sample & 0xff);
147                                                 buffer_num_buffer[output_offset] = (int_sample & 0xff00) >> 8;
148                                         }
149                                 }
150                                 break;
152                         case 24:
153                                 output_advance = (device_channels - 1) * 3;
154                                 for(output_offset = channel * 3, input_offset = 0; 
155                                         input_offset < samples; 
156                                         output_offset += output_advance, input_offset++)
157                                 {
158                                         sample = buffer_in_channel[input_offset];
159                                         CLAMP(sample, -1, 1);
160                                         sample *= 0x7fffff;
161                                         int_sample = (int)sample;
162                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
163                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
164                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
165                                 }
166                                 break;
168                         case 32:
169                                 output_advance = (device_channels - 1) * 4;
170                                 for(output_offset = channel * 4, input_offset = 0; 
171                                         input_offset < samples; 
172                                         output_offset += output_advance, input_offset++)
173                                 {
174                                         sample = buffer_in_channel[input_offset];
175                                         CLAMP(sample, -1, 1);
176                                         sample *= 0x7fffffff;
177                                         int_sample = (int)sample;
178                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
179                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
180                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
181                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff000000) >> 24;
182                                 }
183                                 break;
184                 }
185         }
187 // make buffer available for playback
188         play_lock[buffer_num]->unlock();
189         return 0;
192 int AudioDevice::reset_output()
194         for(int i = 0; i < TOTAL_BUFFERS; i++)
195         {
196                 delete [] output_buffer[i];
197                 output_buffer[i] = 0;
198                 buffer_size[i] = 0;
199                 arm_lock[i]->reset();
200                 play_lock[i]->reset(); 
201                 last_buffer[i] = 0;
202         }
204         is_playing_back = 0;
205         software_position_info = 0;
206         position_correction = 0;
207         last_buffer_size = 0;
208         total_samples = 0;
209         play_dither == 0;
210         arm_buffer_num = 0;
211         last_position = 0;
212         interrupt = 0;
213         return 0;
217 int AudioDevice::set_play_dither(int status)
219         play_dither = status;
220         return 0;
223 int AudioDevice::set_software_positioning(int status)
225         software_position_info = status;
226         return 0;
229 int AudioDevice::start_playback()
231 // arm buffer before doing this
232         is_playing_back = 1;
233         interrupt = 0;
234 // zero timers
235         playback_timer->update();
236         last_position = 0;
238         Thread::set_realtime(get_orealtime());
239         Thread::start();                  // synchronize threads by starting playback here and blocking
242 int AudioDevice::interrupt_playback()
244         interrupt = 1;
246         if(is_playing_back)
247         {
248 // cancel thread
249                 is_playing_back = 0;
250                 get_lowlevel_out()->interrupt_playback();
251 // Completion is waited for in arender
252         }
254 // unlock everything
255         for(int i = 0; i < TOTAL_BUFFERS; i++)
256         {
257 // When TRACE_LOCKS is enabled, this
258 // locks up when run() is waiting on it at just the right time.
259 // Seems there may be a cancel after the trace lock is locked.
260                 play_lock[i]->unlock();  
261                 arm_lock[i]->unlock();
262         }
264         return 0;
267 int AudioDevice::wait_for_startup()
269         startup_lock->lock("AudioDevice::wait_for_startup");
270         return 0;
273 int AudioDevice::wait_for_completion()
275         Thread::join();
276         return 0;
281 int64_t AudioDevice::current_position()
283 // try to get OSS position
284         int64_t hardware_result = 0, software_result = 0, frame;
286         if(w)
287         {
288                 frame = get_obits() / 8;
290 // get hardware position
291                 if(!software_position_info)
292                 {
293                         hardware_result = get_lowlevel_out()->device_position();
294                 }
296 // get software position
297                 if(hardware_result < 0 || software_position_info)
298                 {
299                         timer_lock->lock("AudioDevice::current_position");
300                         software_result = total_samples - last_buffer_size - 
301                                 device_buffer / frame / get_ochannels();
302                         software_result += playback_timer->get_scaled_difference(get_orate());
303                         timer_lock->unlock();
305                         if(software_result < last_position) 
306                                 software_result = last_position;
307                         else
308                                 last_position = software_result;
309                 }
311                 int64_t offset_samples = -(int64_t)(get_orate() * 
312                         out_config->audio_offset);
314                 if(hardware_result < 0 || software_position_info) 
315                         return software_result + offset_samples;
316                 else
317                         return hardware_result + offset_samples;
318         }
319         else
320         if(r)
321         {
322                 int64_t result = total_samples_read + 
323                         record_timer->get_scaled_difference(get_irate());
324                 return result;
325         }
327         return 0;
330 void AudioDevice::run_output()
332         thread_buffer_num = 0;
334         startup_lock->unlock();
335         playback_timer->update();
338 //printf("AudioDevice::run 1 %d\n", Thread::calculate_realtime());
339         while(is_playing_back && !interrupt && !last_buffer[thread_buffer_num])
340         {
341 // wait for buffer to become available
342                 play_lock[thread_buffer_num]->lock("AudioDevice::run 1");
344                 if(is_playing_back && !last_buffer[thread_buffer_num])
345                 {
346                         if(duplex_init)
347                         {
348                                 if(record_before_play)
349                                 {
350 // block until recording starts
351                                         duplex_lock->lock("AudioDevice::run 2");
352                                 }
353                                 else
354                                 {
355 // allow recording to start
356                                         duplex_lock->unlock();
357                                 }
358                                 duplex_init = 0;
359                         }
361 // get size for position information
362                         timer_lock->lock("AudioDevice::run 3");
363                         last_buffer_size = buffer_size[thread_buffer_num] / (get_obits() / 8) / get_ochannels();
364                         total_samples += last_buffer_size;
365                         playback_timer->update();
366                         timer_lock->unlock();
369 // write converted buffer synchronously
370                         thread_result = get_lowlevel_out()->write_buffer(
371                                 output_buffer[thread_buffer_num], 
372                                 buffer_size[thread_buffer_num]);
374 // allow writing to the buffer
375                         arm_lock[thread_buffer_num]->unlock();
377 // inform user if the buffer write failed
378                         if(thread_result < 0)
379                         {
380                                 perror("AudioDevice::write_buffer");
381                                 sleep(1);
382                         }
384                         thread_buffer_num++;
385                         if(thread_buffer_num >= TOTAL_BUFFERS) thread_buffer_num = 0;
386                 }
389 //printf("AudioDevice::run 1 %d %d\n", interrupt, last_buffer[thread_buffer_num]);
390 // test for last buffer
391                 if(!interrupt && last_buffer[thread_buffer_num])
392                 {
393 // no more buffers
394                         is_playing_back = 0;
395 // flush the audio device
396                         get_lowlevel_out()->flush_device();
397                 }
398         }