1 #include "audiodevice.h"
4 #include "bcprogressbox.h"
7 int AudioDevice::set_record_dither(int bits)
14 int AudioDevice::get_dc_offset(int *output, RecordGUIDCOffsetText **dc_offset_text)
16 dc_offset_thread->calibrate_dc_offset(output, dc_offset_text, get_ichannels());
20 int AudioDevice::set_dc_offset(int dc_offset, int channel)
22 dc_offset_thread->dc_offset[channel] = dc_offset;
26 #define GET_PEAK_MACRO \
27 input_channel[j] = sample; \
28 if(sample > max[i]) max[i] = sample; \
29 else if(-sample > max[i]) max[i] = -sample;
31 // ============================ use 2 macros to allow for getting dc_offset
32 // ============= must check for overload after dc_offset because of byte wrapping on save
34 #define GET_8BIT_SAMPLE_MACRO1 \
35 sample = input_buffer[k]; \
36 sample -= dc_offset_value; \
37 k += input_channels; \
38 if(sample >= max_sample[i]) { sample = max_sample[i]; if(over_count < 3) over_count++; } \
40 if(sample <= min_sample[i]) { sample = min_sample[i]; if(over_count < 3) over_count++; } \
42 if(over_count < 3) over_count = 0;
44 #define GET_8BIT_SAMPLE_MACRO2 \
49 #define GET_16BIT_SAMPLE_MACRO1 \
50 sample = input_buffer_16[k]; \
51 if(dither_scale) { dither_value = rand() % dither_scale; sample -= dither_value; } \
52 sample -= dc_offset_value; \
53 k += input_channels; \
54 if(sample >= max_sample[i]) { sample = max_sample[i]; if(over_count < 3) over_count++; } \
56 if(sample <= min_sample[i]) { sample = min_sample[i]; if(over_count < 3) over_count++; } \
58 if(over_count < 3) over_count = 0; \
60 #define GET_16BIT_SAMPLE_MACRO2 \
65 #define GET_24BIT_SAMPLE_MACRO1 \
66 sample = (unsigned char)input_buffer[k] | \
67 (((unsigned char)input_buffer[k + 1]) << 8) | \
68 (((int)input_buffer[k + 2]) << 16); \
69 sample -= dc_offset_value; \
70 k += input_channels * 3; \
71 if(sample >= max_sample[i]) { sample = max_sample[i]; if(over_count < 3) over_count++; } \
73 if(sample <= min_sample[i]) { sample = min_sample[i]; if(over_count < 3) over_count++; } \
75 if(over_count < 3) over_count = 0;
77 #define GET_24BIT_SAMPLE_MACRO2 \
82 #define GET_32BIT_SAMPLE_MACRO1 \
83 sample = (unsigned char)input_buffer[k] | \
84 (((unsigned char)input_buffer[k + 1]) << 8) | \
85 (((unsigned char)input_buffer[k + 2]) << 16) | \
86 (((int)input_buffer[k + 3]) << 24); \
87 sample -= dc_offset_value; \
88 k += input_channels * 4; \
89 if(sample >= max_sample[i]) { sample = max_sample[i]; if(over_count < 3) over_count++; } \
91 if(sample <= min_sample[i]) { sample = min_sample[i]; if(over_count < 3) over_count++; } \
93 if(over_count < 3) over_count = 0;
95 #define GET_32BIT_SAMPLE_MACRO2 \
98 int AudioDevice::read_buffer(double **input,
105 int i, j, k, frame, bits;
106 double sample, denominator;
107 double min_sample[MAXCHANNELS], max_sample[MAXCHANNELS];
110 int dither_value, dither_scale;
113 double *input_channel;
114 int *dc_offset_total;
118 record_timer.update();
121 input_channels = get_ichannels();
122 frame = input_channels * bits / 8;
125 total_samples_read += samples;
133 denominator = 0x7fff;
140 denominator = 0x7fffff;
143 dither_scale = 65535;
146 if (rec_dither == 16)
152 denominator = 0x7fffffff;
157 if(input_buffer == 0) input_buffer = new char[samples * frame];
159 if(duplex_init && !record_before_play)
161 // block until playback starts
162 duplex_lock->lock("AudioDevice::read_buffer");
166 result = get_lowlevel_in()->read_buffer(input_buffer, samples * frame);
168 // allow playback to start
169 if(duplex_init && record_before_play)
171 duplex_lock->unlock();
178 perror("AudioDevice::read_buffer");
182 for(i = 0; i < channels && i < get_ichannels(); i++)
184 input_channel = &input[i][input_offset];
185 dc_offset_value = dc_offset_thread->dc_offset[i];
187 // calculate minimum and maximum samples
188 if(dc_offset_thread->dc_offset[i] <= 0)
190 min_sample[i] = -denominator - dc_offset_thread->dc_offset[i];
191 max_sample[i] = denominator;
195 min_sample[i] = -denominator;
196 max_sample[i] = denominator - dc_offset_thread->dc_offset[i];
201 // device is set to little endian
205 if(dc_offset_thread->getting_dc_offset)
207 dc_offset_total = &(dc_offset_thread->dc_offset_total[i]);
208 for(j = 0, k = i; j < samples; j++)
210 GET_8BIT_SAMPLE_MACRO1
211 (*dc_offset_total) += (int)sample;
212 GET_8BIT_SAMPLE_MACRO2
218 for(j = 0, k = i; j < samples; j++)
220 GET_8BIT_SAMPLE_MACRO1
221 GET_8BIT_SAMPLE_MACRO2
229 int16_t *input_buffer_16;
230 input_buffer_16 = (int16_t *)input_buffer;
231 dc_offset_total = &(dc_offset_thread->dc_offset_total[i]);
233 if(dc_offset_thread->getting_dc_offset)
235 for(j = 0, k = i; j < samples; j++)
237 GET_16BIT_SAMPLE_MACRO1
238 (*dc_offset_total) += (int)sample;
239 GET_16BIT_SAMPLE_MACRO2
245 for(j = 0, k = i; j < samples; j++)
247 GET_16BIT_SAMPLE_MACRO1
248 GET_16BIT_SAMPLE_MACRO2
257 dc_offset_total = &(dc_offset_thread->dc_offset_total[i]);
259 if(dc_offset_thread->getting_dc_offset)
261 for(j = 0, k = i * 3; j < samples; j++)
263 GET_24BIT_SAMPLE_MACRO1
264 (*dc_offset_total) += (int)sample;
265 GET_24BIT_SAMPLE_MACRO2
271 for(j = 0, k = i * 3; j < samples; j++)
273 GET_24BIT_SAMPLE_MACRO1
274 GET_24BIT_SAMPLE_MACRO2
282 dc_offset_total = &(dc_offset_thread->dc_offset_total[i]);
284 if(dc_offset_thread->getting_dc_offset)
286 for(j = 0, k = i * 4; j < samples; j++)
288 GET_32BIT_SAMPLE_MACRO1
289 (*dc_offset_total) += (int)sample;
290 GET_32BIT_SAMPLE_MACRO2
296 for(j = 0, k = i * 4; j < samples; j++)
298 GET_32BIT_SAMPLE_MACRO1
299 GET_32BIT_SAMPLE_MACRO2
306 if(over_count >= 3) over[i] = 1; else over[i] = 0;
309 if(dc_offset_thread->getting_dc_offset)
311 dc_offset_thread->dc_offset_count += samples * channels;
312 if(dc_offset_thread->progress->update(dc_offset_thread->dc_offset_count, 1))
314 dc_offset_thread->getting_dc_offset = 0;
315 dc_offset_thread->dc_offset_lock->unlock();
318 if(dc_offset_thread->dc_offset_count > 256000)
320 for(i = 0; i < get_ichannels(); i++)
322 dc_offset_thread->dc_offset[i] = dc_offset_thread->dc_offset_total[i] / dc_offset_thread->dc_offset_count * 2; // don't know why * 2
324 dc_offset_thread->getting_dc_offset = 0;
325 dc_offset_thread->dc_offset_lock->unlock();