r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / audioodevice.C
blob0f56d64659f7a6e375cd8d1cadcdd4482710a022
1 #include "audiodevice.h"
3 #include <string.h>
5 int AudioDevice::write_buffer(double **output, int samples, int channels)
7 // find free buffer to fill
8         if(interrupt) return 0;
9         arm_buffer(arm_buffer_num, output, samples, channels);
10         arm_buffer_num++;
11         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
12         return 0;
15 int AudioDevice::set_last_buffer()
17         arm_mutex[arm_buffer_num].lock();
18         last_buffer[arm_buffer_num] = 1;
19         play_mutex[arm_buffer_num].unlock();
20         arm_buffer_num++;
21         if(arm_buffer_num >= TOTAL_BUFFERS) arm_buffer_num = 0;
22         return 0;
26 // must run before threading once to allocate buffers
27 // must send maximum size buffer the first time or risk reallocation while threaded
28 int AudioDevice::arm_buffer(int buffer_num, 
29         double **output, 
30         int samples, 
31         int channels)
33         int bits;
34         int new_size;
36         int i, j;
37         int input_offset;
38         int output_offset;
39         int output_advance;
40         int channel, last_input_channel;
41         double sample;
42         int int_sample, int_sample2;
43         int dither_value;
44         int frame;
45         int device_channels = get_ochannels();
46         char *buffer_num_buffer;
47         double *buffer_in_channel;
49 // for(i = 0; i < 100; i++)
50 //      printf("%.2f ", output[0][i]);
51 // printf("\n");
53 //printf("AudioDevice::arm_buffer 1\n");
54         if(channels == -1) channels = get_ochannels();
55         bits = get_obits();
57 //printf("AudioDevice::arm_buffer 1\n");
58         frame = device_channels * (bits / 8);
59 //      if(bits == 24) frame = 4;
61 //printf("AudioDevice::arm_buffer 1\n");
62         new_size = frame * samples;
64 //printf("AudioDevice::arm_buffer 1\n");
65         if(interrupt) return 1;
67 //printf("AudioDevice::arm_buffer 1 %d\n", buffer_num);
68 // wait for buffer to become available for writing
69         arm_mutex[buffer_num].lock();
70 //printf("AudioDevice::arm_buffer 2\n");
71         if(interrupt) return 1;
73         if(new_size > buffer_size[buffer_num])
74         {
75 // do both buffers before threading to prevent kill during allocation
76 //              for(i = 0; i < 2; i++)
77 //              {
78 //                      if(buffer_size[i] != 0)
79 //                      {
80 //                              delete [] buffer[i];
81 //                      }
82 //                      buffer[i] = new char[new_size];
83 //                      buffer_size[i] = new_size;
84 //              }
85                 if(buffer_size[buffer_num] != 0)
86                 {
87                         delete [] buffer[buffer_num];
88                 }
89                 buffer[buffer_num] = new char[new_size];
90                 buffer_size[buffer_num] = new_size;
91         }
93         buffer_size[buffer_num] = new_size;
95 //printf("AudioDevice::arm_buffer 1\n");
96         buffer_num_buffer = buffer[buffer_num];
97         bzero(buffer_num_buffer, new_size);
98         
99         last_input_channel = channels - 1;
100 // copy data
101 // intel byte order only to correspond with bits_to_fmt
103 //printf("AudioDevice::arm_buffer 1\n");
104         for(channel = 0; channel < device_channels && channel < channels; channel++)
105         {
106 //              if(channel >= channels) buffer_in_channel = output[last_input_channel];
107 //              else buffer_in_channel = output[channel];
109                 buffer_in_channel = output[channel];
110                 switch(bits)
111                 {
112                         case 8:
113                                 output_advance = device_channels;
114                                 if(play_dither)
115                                 {
116                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
117                                         {
118                                                 sample = buffer_in_channel[input_offset];
119                                                 sample *= 0x7fff;
120                                                 int_sample = (int)sample;
121                                                 dither_value = rand() % 255;
122                                                 int_sample -= dither_value;
123                                                 int_sample /= 0x100;
124                                                 buffer_num_buffer[output_offset] = int_sample;
125                                         }
126                                 }
127                                 else
128                                 {
129                                         for(output_offset = channel, input_offset = 0; input_offset < samples; output_offset += output_advance, input_offset++)
130                                         {
131                                                 sample = buffer_in_channel[input_offset];
132                                                 sample *= 0x7f;
133                                                 int_sample = (int)sample;
134                                                 buffer_num_buffer[output_offset] = int_sample;
135                                         }
136                                 }
137                                 break;
139                         case 16:
140                                 output_advance = device_channels * 2 - 1;
141                                 if(play_dither)
142                                 {
143                                         for(output_offset = channel * 2, input_offset = 0; 
144                                                 input_offset < samples; 
145                                                 output_offset += output_advance, input_offset++)
146                                         {
147                                                 sample = buffer_in_channel[input_offset];
148                                                 sample *= 0x7fffff;
149                                                 int_sample = (int)sample;
150                                                 dither_value = rand() % 255;
151                                                 int_sample -= dither_value;
152                                                 int_sample /= 0x100;
153                                                 buffer_num_buffer[output_offset] = int_sample;
154                                         }
155                                 }
156                                 else
157                                 {
158                                         for(output_offset = channel * 2, input_offset = 0; 
159                                                 input_offset < samples; 
160                                                 output_offset += output_advance, input_offset++)
161                                         {
162                                                 sample = buffer_in_channel[input_offset];
163                                                 sample *= 0x7fff;
164                                                 int_sample = (int)sample;
165                                                 buffer_num_buffer[output_offset++] = (int_sample & 0xff);
166                                                 buffer_num_buffer[output_offset] = (int_sample & 0xff00) >> 8;
167                                         }
168                                 }
169                                 break;
171                         case 24:
172                                 output_advance = (device_channels - 1) * 3;
173                                 for(output_offset = channel * 3, input_offset = 0; 
174                                         input_offset < samples; 
175                                         output_offset += output_advance, input_offset++)
176                                 {
177                                         sample = buffer_in_channel[input_offset];
178                                         sample *= 0x7fffff;
179                                         int_sample = (int)sample;
180                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
181                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
182                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
183                                 }
184                                 break;
186                         case 32:
187                                 output_advance = (device_channels - 1) * 4;
188                                 for(output_offset = channel * 4, input_offset = 0; 
189                                         input_offset < samples; 
190                                         output_offset += output_advance, input_offset++)
191                                 {
192                                         sample = buffer_in_channel[input_offset];
193                                         sample *= 0x7fffffff;
194                                         int_sample = (int)sample;
195                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff);
196                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff00) >> 8;
197                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff0000) >> 16;
198                                         buffer_num_buffer[output_offset++] = (int_sample & 0xff000000) >> 24;
199                                 }
200                                 break;
201                 }
202         }
204 //printf("AudioDevice::arm_buffer 2\n");
205 // make buffer available for playback
206         play_mutex[buffer_num].unlock();
207         return 0;
210 int AudioDevice::reset_output()
212         for(int i = 0; i < TOTAL_BUFFERS; i++)
213         {
214                 if(buffer_size[i]) { delete [] buffer[i]; }
215                 buffer[i] = 0;
216                 buffer_size[i] = 0;
217                 arm_mutex[i].unlock();
218                 play_mutex[i].reset(); 
219                 play_mutex[i].lock(); 
220                 last_buffer[i] = 0;
221         }
223 // unlock mutexes
224 //complete.unlock();
225         is_playing_back = 0;
226         software_position_info = position_correction = last_buffer_size = 0;
227         total_samples = 0;
228         play_dither == 0;
229         arm_buffer_num = 0;
230         last_position = 0;
231         interrupt = 0;
232         return 0;
236 int AudioDevice::set_play_dither(int status)
238         play_dither = status;
239         return 0;
242 int AudioDevice::set_software_positioning(int status)
244         software_position_info = status;
245         return 0;
248 int AudioDevice::start_playback()
250 // arm buffer before doing this
251         is_playing_back = 1;
252         interrupt = 0;
253 // zero timers
254         playback_timer.update();
255         last_position = 0;
256         startup_lock.lock();
258         Thread::set_realtime(get_orealtime());
259         Thread::start();                  // synchronize threads by starting playback here and blocking
262 int AudioDevice::interrupt_playback()
264         interrupt = 1;
266         if(is_playing_back)
267         {
268 // cancel thread
269                 is_playing_back = 0;
270                 get_lowlevel_out()->interrupt_playback();
271 //              Thread::cancel();
272 // Completion is waited for in arender
273         }
275 // unlock everything
276         for(int i = 0; i < TOTAL_BUFFERS; i++)
277         {
278 //              play_mutex[i].reset();
279 // Caused a crash when run() was waiting on it in original versions.
280 // This is required now since thread cancelation is only possible during
281 // write().
282                 play_mutex[i].unlock();  
283                 arm_mutex[i].unlock();
284         }
286         return 0;
289 int AudioDevice::wait_for_startup()
291         startup_lock.lock();
292         startup_lock.unlock();
293         return 0;
296 int AudioDevice::wait_for_completion()
298         Thread::join();
299         return 0;
304 int64_t AudioDevice::current_position()
306 // try to get OSS position
307         int64_t hardware_result = 0, software_result = 0, frame;
309         if(w)
310         {
311                 frame = get_obits() / 8;
312 //              if(get_obits() == 24) frame = 4;
314 // get hardware position
315                 if(!software_position_info)
316                 {
317                         hardware_result = get_lowlevel_out()->device_position();
318                 }
320 // get software position
321                 if(hardware_result < 0 || software_position_info)
322                 {
323                         timer_lock.lock();
324                         software_result = total_samples - last_buffer_size - 
325                                 device_buffer / frame / get_ochannels();
326                         software_result += playback_timer.get_scaled_difference(get_orate());
327                         timer_lock.unlock();
329                         if(software_result < last_position) 
330                         software_result = last_position;
331                         else
332                         last_position = software_result;
333                 }
334         }
335         else
336         if(r)
337         {
338 //printf("AudioDevice 1\n");
339                 return total_samples_read + record_timer.get_scaled_difference(get_irate());
340 //printf("AudioDevice 2\n");
341         }
343         if(hardware_result < 0 || software_position_info) 
344                 return software_result;
345         else
346                 return hardware_result;
347         return 0;
350 void AudioDevice::run()
352         thread_buffer_num = 0;
354         startup_lock.unlock();
355         playback_timer.update();
357         while(is_playing_back && !interrupt && !last_buffer[thread_buffer_num])
358         {
359 // wait for buffer to become available
360                 play_mutex[thread_buffer_num].lock();
362                 if(is_playing_back && !last_buffer[thread_buffer_num])
363                 {
364                         if(duplex_init)
365                         {
366                                 if(record_before_play)
367                                 {
368 // block until recording starts
369                                         duplex_lock.lock();
370                                 }
371                                 else
372                                 {
373 // allow recording to start
374                                         duplex_lock.unlock();
375                                 }
376                                 duplex_init = 0;
377                         }
379 // get size for position information
380                         timer_lock.lock();
381                         last_buffer_size = buffer_size[thread_buffer_num] / (get_obits() / 8) / get_ochannels();
382                         total_samples += last_buffer_size;
383                         playback_timer.update();
384                         timer_lock.unlock();
386 // write buffer
387                         thread_result = get_lowlevel_out()->write_buffer(buffer[thread_buffer_num], buffer_size[thread_buffer_num]);
389 // allow writing to the buffer
390                         arm_mutex[thread_buffer_num].unlock();
392 // inform user if the buffer write failed
393                         if(thread_result < 0)
394                         {
395                                 perror("AudioDevice::write_buffer");
396                                 sleep(1);
397                         }
399                         thread_buffer_num++;
400                         if(thread_buffer_num >= TOTAL_BUFFERS) thread_buffer_num = 0;
401                 }
403 // test for last buffer
404                 if(!interrupt && last_buffer[thread_buffer_num])
405                 {
406 // no more buffers
407                         is_playing_back = 0;
408 // flush the audio device
409                         get_lowlevel_out()->flush_device();
410                 }
411         }