r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / audioodevice.C
blob09e58056e0a4dae76e8b6102af0fc3c1a0803105
1 #include "audiodevice.h"
2 #include "condition.h"
3 #include "mutex.h"
5 #include <string.h>
7 int AudioDevice::write_buffer(double **output, int samples, int channels)
9 // find free buffer to fill
10         if(interrupt) return 0;
11         arm_buffer(arm_buffer_num, output, samples, channels);
12         arm_buffer_num++;
13         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
14         return 0;
17 int AudioDevice::set_last_buffer()
19         arm_lock[arm_buffer_num]->lock("AudioDevice::set_last_buffer");
20         last_buffer[arm_buffer_num] = 1;
21         play_lock[arm_buffer_num]->unlock();
24         arm_buffer_num++;
25         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
26         return 0;
30 // must run before threading once to allocate buffers
31 // must send maximum size buffer the first time or risk reallocation while threaded
32 int AudioDevice::arm_buffer(int buffer_num, 
33         double **output, 
34         int samples, 
35         int channels)
37         int bits;
38         int new_size;
40         int i, j;
41         int input_offset;
42         int output_offset;
43         int output_advance;
44         int channel, last_input_channel;
45         double sample;
46         int int_sample, int_sample2;
47         int dither_value;
48         int frame;
49         int device_channels = get_ochannels();
50         char *buffer_num_buffer;
51         double *buffer_in_channel;
53         if(channels == -1) channels = get_ochannels();
54         bits = get_obits();
56         frame = device_channels * (bits / 8);
58         new_size = frame * samples;
60         if(interrupt) return 1;
62 // wait for buffer to become available for writing
63         arm_lock[buffer_num]->lock("AudioDevice::arm_buffer");
64         if(interrupt) return 1;
66         if(new_size > buffer_size[buffer_num])
67         {
68                 if(buffer_size[buffer_num] != 0)
69                 {
70                         delete [] buffer[buffer_num];
71                 }
72                 buffer[buffer_num] = new char[new_size];
73                 buffer_size[buffer_num] = new_size;
74         }
76         buffer_size[buffer_num] = new_size;
78         buffer_num_buffer = buffer[buffer_num];
79         bzero(buffer_num_buffer, new_size);
80         
81         last_input_channel = channels - 1;
82 // copy data
83 // intel byte order only to correspond with bits_to_fmt
85         for(channel = 0; channel < device_channels && channel < channels; channel++)
86         {
87                 buffer_in_channel = output[channel];
88                 switch(bits)
89                 {
90                         case 8:
91                                 output_advance = device_channels;
92                                 if(play_dither)
93                                 {
94                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
95                                         {
96                                                 sample = buffer_in_channel[input_offset];
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                                                 sample *= 0x7f;
111                                                 int_sample = (int)sample;
112                                                 buffer_num_buffer[output_offset] = int_sample;
113                                         }
114                                 }
115                                 break;
117                         case 16:
118                                 output_advance = device_channels * 2 - 1;
119                                 if(play_dither)
120                                 {
121                                         for(output_offset = channel * 2, input_offset = 0; 
122                                                 input_offset < samples; 
123                                                 output_offset += output_advance, input_offset++)
124                                         {
125                                                 sample = buffer_in_channel[input_offset];
126                                                 sample *= 0x7fffff;
127                                                 int_sample = (int)sample;
128                                                 dither_value = rand() % 255;
129                                                 int_sample -= dither_value;
130                                                 int_sample /= 0x100;
131                                                 buffer_num_buffer[output_offset] = int_sample;
132                                         }
133                                 }
134                                 else
135                                 {
136                                         for(output_offset = channel * 2, input_offset = 0; 
137                                                 input_offset < samples; 
138                                                 output_offset += output_advance, input_offset++)
139                                         {
140                                                 sample = buffer_in_channel[input_offset];
141                                                 sample *= 0x7fff;
142                                                 int_sample = (int)sample;
143                                                 buffer_num_buffer[output_offset++] = (int_sample & 0xff);
144                                                 buffer_num_buffer[output_offset] = (int_sample & 0xff00) >> 8;
145                                         }
146                                 }
147                                 break;
149                         case 24:
150                                 output_advance = (device_channels - 1) * 3;
151                                 for(output_offset = channel * 3, input_offset = 0; 
152                                         input_offset < samples; 
153                                         output_offset += output_advance, input_offset++)
154                                 {
155                                         sample = buffer_in_channel[input_offset];
156                                         sample *= 0x7fffff;
157                                         int_sample = (int)sample;
158                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
159                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
160                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
161                                 }
162                                 break;
164                         case 32:
165                                 output_advance = (device_channels - 1) * 4;
166                                 for(output_offset = channel * 4, input_offset = 0; 
167                                         input_offset < samples; 
168                                         output_offset += output_advance, input_offset++)
169                                 {
170                                         sample = buffer_in_channel[input_offset];
171                                         sample *= 0x7fffffff;
172                                         int_sample = (int)sample;
173                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
174                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
175                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
176                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff000000) >> 24;
177                                 }
178                                 break;
179                 }
180         }
182 // make buffer available for playback
183         play_lock[buffer_num]->unlock();
184         return 0;
187 int AudioDevice::reset_output()
189         for(int i = 0; i < TOTAL_BUFFERS; i++)
190         {
191                 if(buffer_size[i]) { delete [] buffer[i]; }
192                 buffer[i] = 0;
193                 buffer_size[i] = 0;
194                 arm_lock[i]->reset();
195                 play_lock[i]->reset(); 
196                 last_buffer[i] = 0;
197         }
199         is_playing_back = 0;
200         software_position_info = position_correction = last_buffer_size = 0;
201         total_samples = 0;
202         play_dither == 0;
203         arm_buffer_num = 0;
204         last_position = 0;
205         interrupt = 0;
206         return 0;
210 int AudioDevice::set_play_dither(int status)
212         play_dither = status;
213         return 0;
216 int AudioDevice::set_software_positioning(int status)
218         software_position_info = status;
219         return 0;
222 int AudioDevice::start_playback()
224 // arm buffer before doing this
225         is_playing_back = 1;
226         interrupt = 0;
227 // zero timers
228         playback_timer.update();
229         last_position = 0;
231         Thread::set_realtime(get_orealtime());
232         Thread::start();                  // synchronize threads by starting playback here and blocking
235 int AudioDevice::interrupt_playback()
237         interrupt = 1;
239         if(is_playing_back)
240         {
241 // cancel thread
242                 is_playing_back = 0;
243                 get_lowlevel_out()->interrupt_playback();
244 //              Thread::cancel();
245 // Completion is waited for in arender
246         }
248 // unlock everything
249         for(int i = 0; i < TOTAL_BUFFERS; i++)
250         {
251 //              play_lock[i].reset();
252 // Caused a crash when run() was waiting on it in original versions.
253 // This is required now since thread cancelation is only possible during
254 // write().
255                 play_lock[i]->unlock();  
256                 arm_lock[i]->unlock();
257         }
259         return 0;
262 int AudioDevice::wait_for_startup()
264         startup_lock->lock("AudioDevice::wait_for_startup");
265         return 0;
268 int AudioDevice::wait_for_completion()
270         Thread::join();
271         return 0;
276 int64_t AudioDevice::current_position()
278 // try to get OSS position
279         int64_t hardware_result = 0, software_result = 0, frame;
281         if(w)
282         {
283                 frame = get_obits() / 8;
284 //              if(get_obits() == 24) frame = 4;
286 // get hardware position
287                 if(!software_position_info)
288                 {
289                         hardware_result = get_lowlevel_out()->device_position();
290                 }
292 // get software position
293                 if(hardware_result < 0 || software_position_info)
294                 {
295                         timer_lock->lock("AudioDevice::current_position");
296                         software_result = total_samples - last_buffer_size - 
297                                 device_buffer / frame / get_ochannels();
298                         software_result += playback_timer.get_scaled_difference(get_orate());
299                         timer_lock->unlock();
301                         if(software_result < last_position) 
302                         software_result = last_position;
303                         else
304                         last_position = software_result;
305                 }
306         }
307         else
308         if(r)
309         {
310 //printf("AudioDevice 1\n");
311                 return total_samples_read + record_timer.get_scaled_difference(get_irate());
312 //printf("AudioDevice 2\n");
313         }
315         if(hardware_result < 0 || software_position_info) 
316                 return software_result;
317         else
318                 return hardware_result;
319         return 0;
322 void AudioDevice::run()
324         thread_buffer_num = 0;
326         startup_lock->unlock();
327         playback_timer.update();
329         while(is_playing_back && !interrupt && !last_buffer[thread_buffer_num])
330         {
331 // wait for buffer to become available
332                 play_lock[thread_buffer_num]->lock("AudioDevice::run 1");
334                 if(is_playing_back && !last_buffer[thread_buffer_num])
335                 {
336                         if(duplex_init)
337                         {
338                                 if(record_before_play)
339                                 {
340 // block until recording starts
341                                         duplex_lock->lock("AudioDevice::run 2");
342                                 }
343                                 else
344                                 {
345 // allow recording to start
346                                         duplex_lock->unlock();
347                                 }
348                                 duplex_init = 0;
349                         }
351 // get size for position information
352                         timer_lock->lock("AudioDevice::run 3");
353                         last_buffer_size = buffer_size[thread_buffer_num] / (get_obits() / 8) / get_ochannels();
354                         total_samples += last_buffer_size;
355                         playback_timer.update();
356                         timer_lock->unlock();
359 // write buffer
360                         thread_result = get_lowlevel_out()->write_buffer(buffer[thread_buffer_num], buffer_size[thread_buffer_num]);
362 // allow writing to the buffer
363                         arm_lock[thread_buffer_num]->unlock();
365 // inform user if the buffer write failed
366                         if(thread_result < 0)
367                         {
368                                 perror("AudioDevice::write_buffer");
369                                 sleep(1);
370                         }
372                         thread_buffer_num++;
373                         if(thread_buffer_num >= TOTAL_BUFFERS) thread_buffer_num = 0;
374                 }
377 //printf("AudioDevice::run 1 %d %d\n", interrupt, last_buffer[thread_buffer_num]);
378 // test for last buffer
379                 if(!interrupt && last_buffer[thread_buffer_num])
380                 {
381 // no more buffers
382                         is_playing_back = 0;
383 // flush the audio device
384                         get_lowlevel_out()->flush_device();
385                 }
386         }