r807: Minor fix...
[cinelerra_cv/mob.git] / cinelerra / audioodevice.C
blob1d4c3697f13385c39cfcd02b4f77d01730fca170
1 #include "audiodevice.h"
2 #include "clip.h"
3 #include "condition.h"
4 #include "mutex.h"
5 #include "playbackconfig.h"
6 #include "sema.h"
8 #include <string.h>
10 int AudioDevice::write_buffer(double **output, int samples, int channels)
12 // find free buffer to fill
13         if(interrupt) return 0;
14         arm_buffer(arm_buffer_num, output, samples, channels);
15         arm_buffer_num++;
16         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
17         return 0;
20 int AudioDevice::set_last_buffer()
22         arm_lock[arm_buffer_num]->lock("AudioDevice::set_last_buffer");
23         last_buffer[arm_buffer_num] = 1;
24         play_lock[arm_buffer_num]->unlock();
27         arm_buffer_num++;
28         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
29         return 0;
33 // must run before threading once to allocate buffers
34 // must send maximum size buffer the first time or risk reallocation while threaded
35 int AudioDevice::arm_buffer(int buffer_num, 
36         double **output, 
37         int samples, 
38         int channels)
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         if(channels == -1) channels = get_ochannels();
57         bits = get_obits();
59         frame = device_channels * (bits / 8);
61         new_size = frame * samples;
63         if(interrupt) return 1;
65 // wait for buffer to become available for writing
66         arm_lock[buffer_num]->lock("AudioDevice::arm_buffer");
67         if(interrupt) return 1;
69         if(new_size > buffer_size[buffer_num])
70         {
71                 if(buffer_size[buffer_num] != 0)
72                 {
73                         delete [] buffer[buffer_num];
74                 }
75                 buffer[buffer_num] = new char[new_size];
76                 buffer_size[buffer_num] = new_size;
77         }
79         buffer_size[buffer_num] = new_size;
81         buffer_num_buffer = buffer[buffer_num];
82         bzero(buffer_num_buffer, new_size);
83         
84         last_input_channel = channels - 1;
85 // copy data
86 // intel byte order only to correspond with bits_to_fmt
88         for(channel = 0; channel < device_channels && channel < channels; channel++)
89         {
90                 buffer_in_channel = output[channel];
91                 switch(bits)
92                 {
93                         case 8:
94                                 output_advance = device_channels;
95                                 if(play_dither)
96                                 {
97                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
98                                         {
99                                                 sample = buffer_in_channel[input_offset];
100                                                 CLAMP(sample, -1, 1);
101                                                 sample *= 0x7fff;
102                                                 int_sample = (int)sample;
103                                                 dither_value = rand() % 255;
104                                                 int_sample -= dither_value;
105                                                 int_sample /= 0x100;
106                                                 buffer_num_buffer[output_offset] = int_sample;
107                                         }
108                                 }
109                                 else
110                                 {
111                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
112                                         {
113                                                 sample = buffer_in_channel[input_offset];
114                                                 CLAMP(sample, -1, 1);
115                                                 sample *= 0x7f;
116                                                 int_sample = (int)sample;
117                                                 buffer_num_buffer[output_offset] = int_sample;
118                                         }
119                                 }
120                                 break;
122                         case 16:
123                                 output_advance = device_channels * 2 - 1;
124                                 if(play_dither)
125                                 {
126                                         for(output_offset = channel * 2, input_offset = 0; 
127                                                 input_offset < samples; 
128                                                 output_offset += output_advance, input_offset++)
129                                         {
130                                                 sample = buffer_in_channel[input_offset];
131                                                 CLAMP(sample, -1, 1);
132                                                 sample *= 0x7fffff;
133                                                 int_sample = (int)sample;
134                                                 dither_value = rand() % 255;
135                                                 int_sample -= dither_value;
136                                                 int_sample /= 0x100;
137                                                 buffer_num_buffer[output_offset] = int_sample;
138                                         }
139                                 }
140                                 else
141                                 {
142                                         for(output_offset = channel * 2, input_offset = 0; 
143                                                 input_offset < samples; 
144                                                 output_offset += output_advance, input_offset++)
145                                         {
146                                                 sample = buffer_in_channel[input_offset];
147                                                 CLAMP(sample, -1, 1);
148                                                 sample *= 0x7fff;
149                                                 int_sample = (int)sample;
150                                                 buffer_num_buffer[output_offset++] = (int_sample & 0xff);
151                                                 buffer_num_buffer[output_offset] = (int_sample & 0xff00) >> 8;
152                                         }
153                                 }
154                                 break;
156                         case 24:
157                                 output_advance = (device_channels - 1) * 3;
158                                 for(output_offset = channel * 3, input_offset = 0; 
159                                         input_offset < samples; 
160                                         output_offset += output_advance, input_offset++)
161                                 {
162                                         sample = buffer_in_channel[input_offset];
163                                         CLAMP(sample, -1, 1);
164                                         sample *= 0x7fffff;
165                                         int_sample = (int)sample;
166                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
167                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
168                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
169                                 }
170                                 break;
172                         case 32:
173                                 output_advance = (device_channels - 1) * 4;
174                                 for(output_offset = channel * 4, input_offset = 0; 
175                                         input_offset < samples; 
176                                         output_offset += output_advance, input_offset++)
177                                 {
178                                         sample = buffer_in_channel[input_offset];
179                                         CLAMP(sample, -1, 1);
180                                         sample *= 0x7fffffff;
181                                         int_sample = (int)sample;
182                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
183                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
184                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
185                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff000000) >> 24;
186                                 }
187                                 break;
188                 }
189         }
191 // make buffer available for playback
192         play_lock[buffer_num]->unlock();
193         return 0;
196 int AudioDevice::reset_output()
198         for(int i = 0; i < TOTAL_BUFFERS; i++)
199         {
200                 if(buffer_size[i]) { delete [] buffer[i]; }
201                 buffer[i] = 0;
202                 buffer_size[i] = 0;
203                 arm_lock[i]->reset();
204                 play_lock[i]->reset(); 
205                 last_buffer[i] = 0;
206         }
208         is_playing_back = 0;
209         software_position_info = position_correction = last_buffer_size = 0;
210         total_samples = 0;
211         play_dither == 0;
212         arm_buffer_num = 0;
213         last_position = 0;
214         interrupt = 0;
215         return 0;
219 int AudioDevice::set_play_dither(int status)
221         play_dither = status;
222         return 0;
225 int AudioDevice::set_software_positioning(int status)
227         software_position_info = status;
228         return 0;
231 int AudioDevice::start_playback()
233 // arm buffer before doing this
234         is_playing_back = 1;
235         interrupt = 0;
236 // zero timers
237         playback_timer.update();
238         last_position = 0;
240         Thread::set_realtime(get_orealtime());
241         Thread::start();                  // synchronize threads by starting playback here and blocking
244 int AudioDevice::interrupt_playback()
246         interrupt = 1;
248         if(is_playing_back)
249         {
250 // cancel thread
251                 is_playing_back = 0;
252                 get_lowlevel_out()->interrupt_playback();
253 // Completion is waited for in arender
254         }
256 // unlock everything
257         for(int i = 0; i < TOTAL_BUFFERS; i++)
258         {
259 // When TRACE_LOCKS is enabled, this
260 // locks up when run() is waiting on it at just the right time.
261 // Seems there may be a cancel after the trace lock is locked.
262                 play_lock[i]->unlock();  
263                 arm_lock[i]->unlock();
264         }
266         return 0;
269 int AudioDevice::wait_for_startup()
271         startup_lock->lock("AudioDevice::wait_for_startup");
272         return 0;
275 int AudioDevice::wait_for_completion()
277         Thread::join();
278         return 0;
283 int64_t AudioDevice::current_position()
285 // try to get OSS position
286         int64_t hardware_result = 0, software_result = 0, frame;
288         if(w)
289         {
290                 frame = get_obits() / 8;
292 // get hardware position
293                 if(!software_position_info)
294                 {
295                         hardware_result = get_lowlevel_out()->device_position();
296                 }
298 // get software position
299                 if(hardware_result < 0 || software_position_info)
300                 {
301                         timer_lock->lock("AudioDevice::current_position");
302                         software_result = total_samples - last_buffer_size - 
303                                 device_buffer / frame / get_ochannels();
304                         software_result += playback_timer.get_scaled_difference(get_orate());
305                         timer_lock->unlock();
307                         if(software_result < last_position) 
308                                 software_result = last_position;
309                         else
310                                 last_position = software_result;
311                 }
313                 int64_t offset_samples = -(int64_t)(get_orate() * 
314                         out_config->audio_offset);
316                 if(hardware_result < 0 || software_position_info) 
317                         return software_result + offset_samples;
318                 else
319                         return hardware_result + offset_samples;
320         }
321         else
322         if(r)
323         {
324                 int64_t result = total_samples_read + 
325                         record_timer.get_scaled_difference(get_irate());
326                 return result;
327         }
329         return 0;
332 void AudioDevice::run()
334         thread_buffer_num = 0;
336         startup_lock->unlock();
337         playback_timer.update();
340 //printf("AudioDevice::run 1 %d\n", Thread::calculate_realtime());
341         while(is_playing_back && !interrupt && !last_buffer[thread_buffer_num])
342         {
343 // wait for buffer to become available
344                 play_lock[thread_buffer_num]->lock("AudioDevice::run 1");
346                 if(is_playing_back && !last_buffer[thread_buffer_num])
347                 {
348                         if(duplex_init)
349                         {
350                                 if(record_before_play)
351                                 {
352 // block until recording starts
353                                         duplex_lock->lock("AudioDevice::run 2");
354                                 }
355                                 else
356                                 {
357 // allow recording to start
358                                         duplex_lock->unlock();
359                                 }
360                                 duplex_init = 0;
361                         }
363 // get size for position information
364                         timer_lock->lock("AudioDevice::run 3");
365                         last_buffer_size = buffer_size[thread_buffer_num] / (get_obits() / 8) / get_ochannels();
366                         total_samples += last_buffer_size;
367                         playback_timer.update();
368                         timer_lock->unlock();
371 // write converted buffer synchronously
372                         thread_result = get_lowlevel_out()->write_buffer(buffer[thread_buffer_num], 
373                                 buffer_size[thread_buffer_num]);
375 // allow writing to the buffer
376                         arm_lock[thread_buffer_num]->unlock();
378 // inform user if the buffer write failed
379                         if(thread_result < 0)
380                         {
381                                 perror("AudioDevice::write_buffer");
382                                 sleep(1);
383                         }
385                         thread_buffer_num++;
386                         if(thread_buffer_num >= TOTAL_BUFFERS) thread_buffer_num = 0;
387                 }
390 //printf("AudioDevice::run 1 %d %d\n", interrupt, last_buffer[thread_buffer_num]);
391 // test for last buffer
392                 if(!interrupt && last_buffer[thread_buffer_num])
393                 {
394 // no more buffers
395                         is_playing_back = 0;
396 // flush the audio device
397                         get_lowlevel_out()->flush_device();
398                 }
399         }