Lines 37-45
Link Here
|
37 |
|
37 |
|
38 |
audio_main_device(QDeepCopy<QString>(laudio_main_device)), |
38 |
audio_main_device(QDeepCopy<QString>(laudio_main_device)), |
39 |
audio_passthru_device(QDeepCopy<QString>(laudio_passthru_device)), |
39 |
audio_passthru_device(QDeepCopy<QString>(laudio_passthru_device)), |
40 |
audio_passthru(false), audio_stretchfactor(1.0f), |
40 |
audio_passthru(false), audio_enc(false), |
|
|
41 |
audio_reenc(false), audio_stretchfactor(1.0f), |
41 |
|
42 |
|
42 |
audio_codec(NULL), |
|
|
43 |
source(lsource), killaudio(false), |
43 |
source(lsource), killaudio(false), |
44 |
|
44 |
|
45 |
pauseaudio(false), audio_actually_paused(false), |
45 |
pauseaudio(false), audio_actually_paused(false), |
Lines 54-63
Link Here
|
54 |
pSoundStretch(NULL), |
54 |
pSoundStretch(NULL), |
55 |
encoder(NULL), |
55 |
encoder(NULL), |
56 |
upmixer(NULL), |
56 |
upmixer(NULL), |
|
|
57 |
|
57 |
source_audio_channels(-1), |
58 |
source_audio_channels(-1), |
|
|
59 |
source_audio_samplerate(0), |
58 |
source_audio_bytes_per_sample(0), |
60 |
source_audio_bytes_per_sample(0), |
59 |
needs_upmix(false), |
61 |
needs_upmix(false), |
60 |
surround_mode(FreeSurround::SurroundModePassive), |
62 |
surround_mode(FreeSurround::SurroundModePassive), |
|
|
63 |
old_audio_stretchfactor(1.0), |
61 |
|
64 |
|
62 |
blocking(false), |
65 |
blocking(false), |
63 |
|
66 |
|
Lines 84-89
Link Here
|
84 |
memset(&audiotime_updated, 0, sizeof(audiotime_updated)); |
87 |
memset(&audiotime_updated, 0, sizeof(audiotime_updated)); |
85 |
memset(audiobuffer, 0, sizeof(char) * AUDBUFSIZE); |
88 |
memset(audiobuffer, 0, sizeof(char) * AUDBUFSIZE); |
86 |
configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2); |
89 |
configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2); |
|
|
90 |
orig_config_channels = configured_audio_channels; |
91 |
allow_ac3_passthru = gContext->GetNumSetting("AC3PassThru", false); |
92 |
src_quality = gContext->GetNumSetting("SRCQuality", 2); |
87 |
|
93 |
|
88 |
// You need to call Reconfigure from your concrete class. |
94 |
// You need to call Reconfigure from your concrete class. |
89 |
// Reconfigure(laudio_bits, laudio_channels, |
95 |
// Reconfigure(laudio_bits, laudio_channels, |
Lines 124-163
Link Here
|
124 |
VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1") |
130 |
VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1") |
125 |
.arg(audio_stretchfactor)); |
131 |
.arg(audio_stretchfactor)); |
126 |
pSoundStretch = new soundtouch::SoundTouch(); |
132 |
pSoundStretch = new soundtouch::SoundTouch(); |
127 |
if (audio_codec) |
133 |
pSoundStretch->setSampleRate(audio_samplerate); |
128 |
{ |
134 |
pSoundStretch->setChannels(upmixer ? |
129 |
if (!encoder) |
135 |
configured_audio_channels : source_audio_channels); |
130 |
{ |
|
|
131 |
VERBOSE(VB_AUDIO, LOC + |
132 |
QString("Creating Encoder for codec %1 origfs %2") |
133 |
.arg(audio_codec->codec_id) |
134 |
.arg(audio_codec->frame_size)); |
135 |
|
136 |
encoder = new AudioOutputDigitalEncoder(); |
137 |
if (!encoder->Init(audio_codec->codec_id, |
138 |
audio_codec->bit_rate, |
139 |
audio_codec->sample_rate, |
140 |
audio_codec->channels |
141 |
)) |
142 |
{ |
143 |
// eeks |
144 |
delete encoder; |
145 |
encoder = NULL; |
146 |
VERBOSE(VB_AUDIO, LOC + |
147 |
QString("Failed to Create Encoder")); |
148 |
} |
149 |
} |
150 |
} |
151 |
if (audio_codec && encoder) |
152 |
{ |
153 |
pSoundStretch->setSampleRate(audio_codec->sample_rate); |
154 |
pSoundStretch->setChannels(audio_codec->channels); |
155 |
} |
156 |
else |
157 |
{ |
158 |
pSoundStretch->setSampleRate(audio_samplerate); |
159 |
pSoundStretch->setChannels(audio_channels); |
160 |
} |
161 |
|
136 |
|
162 |
pSoundStretch->setTempo(audio_stretchfactor); |
137 |
pSoundStretch->setTempo(audio_stretchfactor); |
163 |
pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35); |
138 |
pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35); |
Lines 165-171
Link Here
|
165 |
// dont need these with only tempo change |
140 |
// dont need these with only tempo change |
166 |
//pSoundStretch->setPitch(1.0); |
141 |
//pSoundStretch->setPitch(1.0); |
167 |
//pSoundStretch->setRate(1.0); |
142 |
//pSoundStretch->setRate(1.0); |
168 |
|
|
|
169 |
//pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, true); |
143 |
//pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, true); |
170 |
//pSoundStretch->setSetting(SETTING_USE_AA_FILTER, false); |
144 |
//pSoundStretch->setSetting(SETTING_USE_AA_FILTER, false); |
171 |
} |
145 |
} |
Lines 184-218
Link Here
|
184 |
return audio_stretchfactor; |
158 |
return audio_stretchfactor; |
185 |
} |
159 |
} |
186 |
|
160 |
|
|
|
161 |
bool AudioOutputBase::ToggleUpmix(void) |
162 |
{ |
163 |
if (orig_config_channels == 2 || audio_passthru) |
164 |
return false; |
165 |
if (configured_audio_channels == 6) |
166 |
configured_audio_channels = 2; |
167 |
else |
168 |
configured_audio_channels = 6; |
169 |
|
170 |
Reconfigure(audio_bits, source_audio_channels, |
171 |
source_audio_samplerate, audio_passthru); |
172 |
return (configured_audio_channels == 6); |
173 |
} |
174 |
|
187 |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
175 |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
188 |
int laudio_samplerate, bool laudio_passthru, |
176 |
int laudio_samplerate, bool laudio_passthru) |
189 |
void *laudio_codec) |
|
|
190 |
{ |
177 |
{ |
191 |
int codec_id = CODEC_ID_NONE; |
|
|
192 |
int lcodec_id = CODEC_ID_NONE; |
193 |
int lcchannels = 0; |
194 |
int cchannels = 0; |
195 |
int lsource_audio_channels = laudio_channels; |
178 |
int lsource_audio_channels = laudio_channels; |
196 |
bool lneeds_upmix = false; |
179 |
bool lneeds_upmix = false; |
197 |
|
180 |
bool laudio_reenc = false; |
198 |
if (laudio_codec) |
181 |
|
199 |
{ |
182 |
// Are we perhaps reencoding a (previously) timestretched bitstream? |
200 |
lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id; |
183 |
if (laudio_channels > 2 && !laudio_passthru) |
201 |
laudio_bits = 16; |
184 |
laudio_reenc = true; |
202 |
laudio_channels = 2; |
185 |
|
203 |
lsource_audio_channels = laudio_channels; |
186 |
// Enough channels? Upmix if not |
204 |
laudio_samplerate = 48000; |
187 |
if (laudio_channels < configured_audio_channels && !laudio_passthru) |
205 |
lcchannels = ((AVCodecContext*)laudio_codec)->channels; |
|
|
206 |
} |
207 |
|
208 |
if (audio_codec) |
209 |
{ |
210 |
codec_id = audio_codec->codec_id; |
211 |
cchannels = ((AVCodecContext*)audio_codec)->channels; |
212 |
} |
213 |
|
214 |
if ((configured_audio_channels == 6) && |
215 |
!(laudio_codec || audio_codec)) |
216 |
{ |
188 |
{ |
217 |
laudio_channels = configured_audio_channels; |
189 |
laudio_channels = configured_audio_channels; |
218 |
lneeds_upmix = true; |
190 |
lneeds_upmix = true; |
Lines 225-231
Link Here
|
225 |
laudio_samplerate == audio_samplerate && !need_resampler && |
197 |
laudio_samplerate == audio_samplerate && !need_resampler && |
226 |
laudio_passthru == audio_passthru && |
198 |
laudio_passthru == audio_passthru && |
227 |
lneeds_upmix == needs_upmix && |
199 |
lneeds_upmix == needs_upmix && |
228 |
lcodec_id == codec_id && lcchannels == cchannels); |
200 |
laudio_reenc == audio_reenc); |
229 |
bool upmix_deps = |
201 |
bool upmix_deps = |
230 |
(lsource_audio_channels == source_audio_channels); |
202 |
(lsource_audio_channels == source_audio_channels); |
231 |
if (general_deps && upmix_deps) |
203 |
if (general_deps && upmix_deps) |
Lines 252-263
Link Here
|
252 |
waud = raud = 0; |
224 |
waud = raud = 0; |
253 |
audio_actually_paused = false; |
225 |
audio_actually_paused = false; |
254 |
|
226 |
|
255 |
bool redo_stretch = (pSoundStretch && audio_channels != laudio_channels); |
|
|
256 |
audio_channels = laudio_channels; |
227 |
audio_channels = laudio_channels; |
257 |
source_audio_channels = lsource_audio_channels; |
228 |
source_audio_channels = lsource_audio_channels; |
258 |
audio_bits = laudio_bits; |
229 |
audio_bits = laudio_bits; |
259 |
audio_samplerate = laudio_samplerate; |
230 |
source_audio_samplerate = audio_samplerate = laudio_samplerate; |
260 |
audio_codec = (AVCodecContext*)laudio_codec; |
231 |
audio_reenc = laudio_reenc; |
261 |
audio_passthru = laudio_passthru; |
232 |
audio_passthru = laudio_passthru; |
262 |
needs_upmix = lneeds_upmix; |
233 |
needs_upmix = lneeds_upmix; |
263 |
|
234 |
|
Lines 268-275
Link Here
|
268 |
Error("AudioOutput only supports 8 or 16bit audio."); |
239 |
Error("AudioOutput only supports 8 or 16bit audio."); |
269 |
return; |
240 |
return; |
270 |
} |
241 |
} |
271 |
audio_bytes_per_sample = audio_channels * audio_bits / 8; |
|
|
272 |
source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8; |
273 |
|
242 |
|
274 |
need_resampler = false; |
243 |
need_resampler = false; |
275 |
killaudio = false; |
244 |
killaudio = false; |
Lines 278-284
Link Here
|
278 |
internal_vol = gContext->GetNumSetting("MythControlsVolume", 0); |
247 |
internal_vol = gContext->GetNumSetting("MythControlsVolume", 0); |
279 |
|
248 |
|
280 |
numlowbuffer = 0; |
249 |
numlowbuffer = 0; |
|
|
250 |
|
251 |
// Encode to AC-3 if not passing thru, there's more than 2 channels |
252 |
// and we're allowed to passthru AC-3 |
253 |
// This won't reencode timestretched 2ch AC-3 but there's no point doing so |
254 |
if (!audio_passthru && audio_channels > 2 && allow_ac3_passthru) |
255 |
{ |
256 |
VERBOSE(VB_AUDIO, LOC + "Creating AC-3 Encoder"); |
257 |
int srate = src_quality == 0 ? audio_samplerate : 48000; |
258 |
encoder = new AudioOutputDigitalEncoder(); |
259 |
if (!encoder->Init(CODEC_ID_AC3, 448000, srate, |
260 |
audio_channels, audio_reenc)) |
261 |
{ |
262 |
VERBOSE(VB_AUDIO, LOC + "Can't create AC-3 encoder"); |
263 |
delete encoder; |
264 |
encoder = NULL; |
265 |
} |
266 |
|
267 |
audio_enc = true; |
268 |
} |
269 |
|
270 |
if(audio_passthru || audio_enc) |
271 |
// AC-3 output - soundcard expects a 2ch 48k stream |
272 |
audio_channels = 2; |
273 |
|
274 |
audio_bytes_per_sample = audio_channels * audio_bits / 8; |
275 |
source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8; |
281 |
|
276 |
|
|
|
277 |
// Always resample to 48k - many cards can't do anything else |
278 |
// and ALSA will do it with linear interpolation (yuk) if we don't anyway |
279 |
if (src_quality != 0 && audio_samplerate != 48000) |
280 |
{ |
281 |
int error; |
282 |
audio_samplerate = 48000; |
283 |
VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2") |
284 |
.arg(laudio_samplerate).arg(audio_samplerate)); |
285 |
src_ctx = src_new(3-src_quality, audio_channels, &error); |
286 |
if (error) |
287 |
{ |
288 |
Error(QString("Error creating resampler, the error was: %1") |
289 |
.arg(src_strerror(error)) ); |
290 |
pthread_mutex_unlock(&avsync_lock); |
291 |
pthread_mutex_unlock(&audio_buflock); |
292 |
src_ctx = NULL; |
293 |
return; |
294 |
} |
295 |
src_data.src_ratio = (double) audio_samplerate / laudio_samplerate; |
296 |
src_data.data_in = src_in; |
297 |
src_data.data_out = src_out; |
298 |
src_data.output_frames = 16384*6; |
299 |
need_resampler = true; |
300 |
} |
301 |
|
282 |
VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2(%3) sr %4") |
302 |
VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2(%3) sr %4") |
283 |
.arg(audio_main_device).arg(audio_channels) |
303 |
.arg(audio_main_device).arg(audio_channels) |
284 |
.arg(source_audio_channels).arg(audio_samplerate)); |
304 |
.arg(source_audio_channels).arg(audio_samplerate)); |
Lines 314-345
Link Here
|
314 |
current_seconds = -1; |
334 |
current_seconds = -1; |
315 |
source_bitrate = -1; |
335 |
source_bitrate = -1; |
316 |
|
336 |
|
317 |
// NOTE: this won't do anything as above samplerate vars are set equal |
|
|
318 |
// Check if we need the resampler |
319 |
if (audio_samplerate != laudio_samplerate) |
320 |
{ |
321 |
int error; |
322 |
VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2") |
323 |
.arg(laudio_samplerate).arg(audio_samplerate)); |
324 |
src_ctx = src_new (SRC_SINC_BEST_QUALITY, audio_channels, &error); |
325 |
if (error) |
326 |
{ |
327 |
Error(QString("Error creating resampler, the error was: %1") |
328 |
.arg(src_strerror(error)) ); |
329 |
pthread_mutex_unlock(&avsync_lock); |
330 |
pthread_mutex_unlock(&audio_buflock); |
331 |
return; |
332 |
} |
333 |
src_data.src_ratio = (double) audio_samplerate / laudio_samplerate; |
334 |
src_data.data_in = src_in; |
335 |
src_data.data_out = src_out; |
336 |
src_data.output_frames = 16384*6; |
337 |
need_resampler = true; |
338 |
} |
339 |
|
340 |
if (needs_upmix) |
337 |
if (needs_upmix) |
341 |
{ |
338 |
{ |
342 |
VERBOSE(VB_AUDIO, LOC + QString("create upmixer")); |
|
|
343 |
if (configured_audio_channels == 6) |
339 |
if (configured_audio_channels == 6) |
344 |
{ |
340 |
{ |
345 |
surround_mode = gContext->GetNumSetting("AudioUpmixType", 2); |
341 |
surround_mode = gContext->GetNumSetting("AudioUpmixType", 2); |
Lines 351-414
Link Here
|
351 |
(FreeSurround::SurroundMode)surround_mode); |
347 |
(FreeSurround::SurroundMode)surround_mode); |
352 |
|
348 |
|
353 |
VERBOSE(VB_AUDIO, LOC + |
349 |
VERBOSE(VB_AUDIO, LOC + |
354 |
QString("create upmixer done with surround mode %1") |
350 |
QString("Create upmixer done with surround mode %1") |
355 |
.arg(surround_mode)); |
351 |
.arg(surround_mode)); |
356 |
} |
352 |
} |
357 |
|
353 |
|
358 |
VERBOSE(VB_AUDIO, LOC + QString("Audio Stretch Factor: %1") |
354 |
VERBOSE(VB_AUDIO, LOC + QString("Audio Stretch Factor: %1") |
359 |
.arg(audio_stretchfactor)); |
355 |
.arg(audio_stretchfactor)); |
360 |
VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1") |
|
|
361 |
.arg((audio_codec) ? |
362 |
codec_id_string(audio_codec->codec_id) : "not set")); |
363 |
|
356 |
|
364 |
if (redo_stretch) |
357 |
SetStretchFactorLocked(old_audio_stretchfactor); |
365 |
{ |
|
|
366 |
float laudio_stretchfactor = audio_stretchfactor; |
367 |
delete pSoundStretch; |
368 |
pSoundStretch = NULL; |
369 |
audio_stretchfactor = 0.0f; |
370 |
SetStretchFactorLocked(laudio_stretchfactor); |
371 |
} |
372 |
else |
373 |
{ |
374 |
SetStretchFactorLocked(audio_stretchfactor); |
375 |
if (pSoundStretch) |
376 |
{ |
377 |
// if its passthru then we need to reencode |
378 |
if (audio_codec) |
379 |
{ |
380 |
if (!encoder) |
381 |
{ |
382 |
VERBOSE(VB_AUDIO, LOC + |
383 |
QString("Creating Encoder for codec %1") |
384 |
.arg(audio_codec->codec_id)); |
385 |
|
386 |
encoder = new AudioOutputDigitalEncoder(); |
387 |
if (!encoder->Init(audio_codec->codec_id, |
388 |
audio_codec->bit_rate, |
389 |
audio_codec->sample_rate, |
390 |
audio_codec->channels |
391 |
)) |
392 |
{ |
393 |
// eeks |
394 |
delete encoder; |
395 |
encoder = NULL; |
396 |
VERBOSE(VB_AUDIO, LOC + "Failed to Create Encoder"); |
397 |
} |
398 |
} |
399 |
} |
400 |
if (audio_codec && encoder) |
401 |
{ |
402 |
pSoundStretch->setSampleRate(audio_codec->sample_rate); |
403 |
pSoundStretch->setChannels(audio_codec->channels); |
404 |
} |
405 |
else |
406 |
{ |
407 |
pSoundStretch->setSampleRate(audio_samplerate); |
408 |
pSoundStretch->setChannels(audio_channels); |
409 |
} |
410 |
} |
411 |
} |
412 |
|
358 |
|
413 |
// Setup visualisations, zero the visualisations buffers |
359 |
// Setup visualisations, zero the visualisations buffers |
414 |
prepareVisuals(); |
360 |
prepareVisuals(); |
Lines 455-464
Link Here
|
455 |
VERBOSE(VB_AUDIO, LOC + "Killing AudioOutputDSP"); |
401 |
VERBOSE(VB_AUDIO, LOC + "Killing AudioOutputDSP"); |
456 |
killaudio = true; |
402 |
killaudio = true; |
457 |
StopOutputThread(); |
403 |
StopOutputThread(); |
|
|
404 |
|
405 |
pthread_mutex_lock(&audio_buflock); |
458 |
|
406 |
|
459 |
// Close resampler? |
407 |
// Close resampler? |
460 |
if (src_ctx) |
408 |
if (src_ctx) |
|
|
409 |
{ |
461 |
src_delete(src_ctx); |
410 |
src_delete(src_ctx); |
|
|
411 |
src_ctx = NULL; |
412 |
} |
413 |
|
462 |
need_resampler = false; |
414 |
need_resampler = false; |
463 |
|
415 |
|
464 |
// close sound stretcher |
416 |
// close sound stretcher |
Lines 466-471
Link Here
|
466 |
{ |
418 |
{ |
467 |
delete pSoundStretch; |
419 |
delete pSoundStretch; |
468 |
pSoundStretch = NULL; |
420 |
pSoundStretch = NULL; |
|
|
421 |
old_audio_stretchfactor = audio_stretchfactor; |
422 |
audio_stretchfactor = 1.0; |
469 |
} |
423 |
} |
470 |
|
424 |
|
471 |
if (encoder) |
425 |
if (encoder) |
Lines 480-488
Link Here
|
480 |
upmixer = NULL; |
434 |
upmixer = NULL; |
481 |
} |
435 |
} |
482 |
needs_upmix = false; |
436 |
needs_upmix = false; |
|
|
437 |
audio_enc = false; |
483 |
|
438 |
|
484 |
CloseDevice(); |
439 |
CloseDevice(); |
485 |
|
440 |
|
|
|
441 |
pthread_mutex_unlock(&audio_buflock); |
486 |
killAudioLock.unlock(); |
442 |
killAudioLock.unlock(); |
487 |
} |
443 |
} |
488 |
|
444 |
|
Lines 591-597
Link Here
|
591 |
ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000; |
547 |
ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000; |
592 |
ret = (long long)(ret * audio_stretchfactor); |
548 |
ret = (long long)(ret * audio_stretchfactor); |
593 |
|
549 |
|
594 |
#if 1 |
|
|
595 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
550 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
596 |
QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7") |
551 |
QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7") |
597 |
.arg(now.tv_sec).arg(now.tv_usec) |
552 |
.arg(now.tv_sec).arg(now.tv_usec) |
Lines 600-606
Link Here
|
600 |
.arg(audiotime) |
555 |
.arg(audiotime) |
601 |
.arg(audio_stretchfactor) |
556 |
.arg(audio_stretchfactor) |
602 |
); |
557 |
); |
603 |
#endif |
|
|
604 |
|
558 |
|
605 |
ret += audiotime; |
559 |
ret += audiotime; |
606 |
|
560 |
|
Lines 638-666
Link Here
|
638 |
|
592 |
|
639 |
soundcard_buffer = getBufferedOnSoundcard(); // bytes |
593 |
soundcard_buffer = getBufferedOnSoundcard(); // bytes |
640 |
totalbuffer = audiolen(false) + soundcard_buffer; |
594 |
totalbuffer = audiolen(false) + soundcard_buffer; |
641 |
|
595 |
|
642 |
// include algorithmic latencies |
596 |
// include algorithmic latencies |
643 |
if (pSoundStretch) |
597 |
if (pSoundStretch) |
644 |
{ |
|
|
645 |
// add the effect of any unused but processed samples, |
646 |
// AC3 reencode does this |
647 |
totalbuffer += (int)(pSoundStretch->numSamples() * |
648 |
audio_bytes_per_sample); |
649 |
// add the effect of unprocessed samples in time stretch algo |
650 |
totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() * |
598 |
totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() * |
651 |
audio_bytes_per_sample) / audio_stretchfactor); |
599 |
audio_bytes_per_sample) / audio_stretchfactor); |
652 |
} |
|
|
653 |
|
600 |
|
654 |
if (upmixer && needs_upmix) |
601 |
if (upmixer && needs_upmix) |
655 |
{ |
|
|
656 |
totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample; |
602 |
totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample; |
657 |
} |
603 |
|
|
|
604 |
if (encoder) |
605 |
totalbuffer += encoder->Buffered(); |
658 |
|
606 |
|
659 |
audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 / |
607 |
audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 / |
660 |
(audio_bytes_per_sample * effdspstretched)); |
608 |
(audio_bytes_per_sample * effdspstretched)); |
661 |
|
609 |
|
662 |
gettimeofday(&audiotime_updated, NULL); |
610 |
gettimeofday(&audiotime_updated, NULL); |
663 |
#if 1 |
611 |
|
664 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
612 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
665 |
QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 " |
613 |
QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 " |
666 |
"tb=%5 sb=%6 eds=%7 abps=%8 sf=%9") |
614 |
"tb=%5 sb=%6 eds=%7 abps=%8 sf=%9") |
Lines 672-678
Link Here
|
672 |
.arg(effdspstretched) |
620 |
.arg(effdspstretched) |
673 |
.arg(audio_bytes_per_sample) |
621 |
.arg(audio_bytes_per_sample) |
674 |
.arg(audio_stretchfactor)); |
622 |
.arg(audio_stretchfactor)); |
675 |
#endif |
|
|
676 |
|
623 |
|
677 |
pthread_mutex_unlock(&avsync_lock); |
624 |
pthread_mutex_unlock(&avsync_lock); |
678 |
pthread_mutex_unlock(&audio_buflock); |
625 |
pthread_mutex_unlock(&audio_buflock); |
Lines 686-692
Link Here
|
686 |
int abps = (encoder) ? |
633 |
int abps = (encoder) ? |
687 |
encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
634 |
encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
688 |
int len = samples * abps; |
635 |
int len = samples * abps; |
689 |
|
636 |
|
690 |
// Check we have enough space to write the data |
637 |
// Check we have enough space to write the data |
691 |
if (need_resampler && src_ctx) |
638 |
if (need_resampler && src_ctx) |
692 |
len = (int)ceilf(float(len) * src_data.src_ratio); |
639 |
len = (int)ceilf(float(len) * src_data.src_ratio); |
Lines 708-713
Link Here
|
708 |
|
655 |
|
709 |
return false; // would overflow |
656 |
return false; // would overflow |
710 |
} |
657 |
} |
|
|
658 |
|
659 |
pthread_mutex_lock(&audio_buflock); |
711 |
|
660 |
|
712 |
// resample input if necessary |
661 |
// resample input if necessary |
713 |
if (need_resampler && src_ctx) |
662 |
if (need_resampler && src_ctx) |
Lines 741-746
Link Here
|
741 |
// Call our function to do the work |
690 |
// Call our function to do the work |
742 |
_AddSamples(buffers, false, samples, timecode); |
691 |
_AddSamples(buffers, false, samples, timecode); |
743 |
} |
692 |
} |
|
|
693 |
|
694 |
pthread_mutex_unlock(&audio_buflock); |
744 |
|
695 |
|
745 |
return true; |
696 |
return true; |
746 |
} |
697 |
} |
Lines 753-758
Link Here
|
753 |
int abps = (encoder) ? |
704 |
int abps = (encoder) ? |
754 |
encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
705 |
encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
755 |
int len = samples * abps; |
706 |
int len = samples * abps; |
|
|
707 |
|
708 |
// Give original samples to mythmusic visualisation |
709 |
dispatchVisual((unsigned char *)buffer, len, timecode, |
710 |
source_audio_channels, audio_bits); |
756 |
|
711 |
|
757 |
// Check we have enough space to write the data |
712 |
// Check we have enough space to write the data |
758 |
if (need_resampler && src_ctx) |
713 |
if (need_resampler && src_ctx) |
Lines 776-781
Link Here
|
776 |
.arg(timecode)); |
731 |
.arg(timecode)); |
777 |
return false; // would overflow |
732 |
return false; // would overflow |
778 |
} |
733 |
} |
|
|
734 |
|
735 |
pthread_mutex_lock(&audio_buflock); |
779 |
|
736 |
|
780 |
// resample input if necessary |
737 |
// resample input if necessary |
781 |
if (need_resampler && src_ctx) |
738 |
if (need_resampler && src_ctx) |
Lines 804-809
Link Here
|
804 |
// Call our function to do the work |
761 |
// Call our function to do the work |
805 |
_AddSamples(buffer, true, samples, timecode); |
762 |
_AddSamples(buffer, true, samples, timecode); |
806 |
} |
763 |
} |
|
|
764 |
|
765 |
pthread_mutex_unlock(&audio_buflock); |
807 |
|
766 |
|
808 |
return true; |
767 |
return true; |
809 |
} |
768 |
} |
Lines 836-845
Link Here
|
836 |
if (src_ctx) |
795 |
if (src_ctx) |
837 |
{ |
796 |
{ |
838 |
int error = src_reset(src_ctx); |
797 |
int error = src_reset(src_ctx); |
839 |
if (error) |
798 |
if (error) |
|
|
799 |
{ |
840 |
VERBOSE(VB_IMPORTANT, LOC_ERR + QString( |
800 |
VERBOSE(VB_IMPORTANT, LOC_ERR + QString( |
841 |
"Error occured while resetting resampler: %1") |
801 |
"Error occured while resetting resampler: %1") |
842 |
.arg(src_strerror(error))); |
802 |
.arg(src_strerror(error))); |
|
|
803 |
src_ctx = NULL; |
804 |
} |
843 |
} |
805 |
} |
844 |
} |
806 |
} |
845 |
} |
807 |
} |
Lines 849-856
Link Here
|
849 |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
811 |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
850 |
long long timecode) |
812 |
long long timecode) |
851 |
{ |
813 |
{ |
852 |
pthread_mutex_lock(&audio_buflock); |
|
|
853 |
|
854 |
int len; // = samples * audio_bytes_per_sample; |
814 |
int len; // = samples * audio_bytes_per_sample; |
855 |
int audio_bytes = audio_bits / 8; |
815 |
int audio_bytes = audio_bits / 8; |
856 |
int org_waud = waud; |
816 |
int org_waud = waud; |
Lines 867-883
Link Here
|
867 |
.arg(samples * abps) |
827 |
.arg(samples * abps) |
868 |
.arg(AUDBUFSIZE-afree).arg(afree).arg(timecode) |
828 |
.arg(AUDBUFSIZE-afree).arg(afree).arg(timecode) |
869 |
.arg(needs_upmix)); |
829 |
.arg(needs_upmix)); |
|
|
830 |
|
831 |
len = WaitForFreeSpace(samples); |
870 |
|
832 |
|
871 |
if (upmixer && needs_upmix) |
833 |
if (upmixer && needs_upmix) |
872 |
{ |
834 |
{ |
873 |
int out_samples = 0; |
835 |
int out_samples = 0; |
|
|
836 |
org_waud = waud; |
874 |
int step = (interleaved)?source_audio_channels:1; |
837 |
int step = (interleaved)?source_audio_channels:1; |
875 |
len = WaitForFreeSpace(samples); // test |
838 |
|
876 |
for (int itemp = 0; itemp < samples; ) |
839 |
for (int itemp = 0; itemp < samples; ) |
877 |
{ |
840 |
{ |
878 |
// just in case it does a processing cycle, release the lock |
|
|
879 |
// to allow the output loop to do output |
880 |
pthread_mutex_unlock(&audio_buflock); |
881 |
if (audio_bytes == 2) |
841 |
if (audio_bytes == 2) |
882 |
{ |
842 |
{ |
883 |
itemp += upmixer->putSamples( |
843 |
itemp += upmixer->putSamples( |
Lines 894-900
Link Here
|
894 |
source_audio_channels, |
854 |
source_audio_channels, |
895 |
(interleaved) ? 0 : samples); |
855 |
(interleaved) ? 0 : samples); |
896 |
} |
856 |
} |
897 |
pthread_mutex_lock(&audio_buflock); |
|
|
898 |
|
857 |
|
899 |
int copy_samples = upmixer->numSamples(); |
858 |
int copy_samples = upmixer->numSamples(); |
900 |
if (copy_samples) |
859 |
if (copy_samples) |
Lines 913-922
Link Here
|
913 |
(short*)(audiobuffer), (copy_samples - bdiff_samples)); |
872 |
(short*)(audiobuffer), (copy_samples - bdiff_samples)); |
914 |
} |
873 |
} |
915 |
else |
874 |
else |
916 |
{ |
|
|
917 |
upmixer->receiveSamples( |
875 |
upmixer->receiveSamples( |
918 |
(short*)(audiobuffer + org_waud), copy_samples); |
876 |
(short*)(audiobuffer + org_waud), copy_samples); |
919 |
} |
877 |
|
920 |
org_waud = (org_waud + copy_len) % AUDBUFSIZE; |
878 |
org_waud = (org_waud + copy_len) % AUDBUFSIZE; |
921 |
} |
879 |
} |
922 |
} |
880 |
} |
Lines 928-935
Link Here
|
928 |
} |
886 |
} |
929 |
else |
887 |
else |
930 |
{ |
888 |
{ |
931 |
len = WaitForFreeSpace(samples); |
|
|
932 |
|
933 |
if (interleaved) |
889 |
if (interleaved) |
934 |
{ |
890 |
{ |
935 |
char *mybuf = (char*)buffer; |
891 |
char *mybuf = (char*)buffer; |
Lines 964-1101
Link Here
|
964 |
} |
920 |
} |
965 |
} |
921 |
} |
966 |
} |
922 |
} |
967 |
|
923 |
|
968 |
if (samples > 0) |
924 |
if (samples <= 0) |
|
|
925 |
return; |
926 |
|
927 |
if (pSoundStretch) |
969 |
{ |
928 |
{ |
970 |
if (pSoundStretch) |
929 |
// does not change the timecode, only the number of samples |
971 |
{ |
930 |
// back to orig pos |
972 |
|
931 |
org_waud = waud; |
973 |
// does not change the timecode, only the number of samples |
932 |
int bdiff = AUDBUFSIZE - org_waud; |
974 |
// back to orig pos |
933 |
int nSamplesToEnd = bdiff/abps; |
975 |
org_waud = waud; |
934 |
if (bdiff < len) |
976 |
int bdiff = AUDBUFSIZE - org_waud; |
935 |
{ |
977 |
int nSamplesToEnd = bdiff/abps; |
936 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
978 |
if (bdiff < len) |
937 |
(audiobuffer + |
979 |
{ |
938 |
org_waud), nSamplesToEnd); |
980 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
939 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer, |
981 |
(audiobuffer + |
940 |
(len - bdiff) / abps); |
982 |
org_waud), nSamplesToEnd); |
941 |
} |
983 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer, |
942 |
else |
984 |
(len - bdiff) / abps); |
943 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
985 |
} |
944 |
(audiobuffer + org_waud), |
986 |
else |
945 |
len / abps); |
987 |
{ |
|
|
988 |
pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
989 |
(audiobuffer + org_waud), |
990 |
len / abps); |
991 |
} |
992 |
|
993 |
if (encoder) |
994 |
{ |
995 |
// pull out a packet's worth and reencode it until we |
996 |
// don't have enough for any more packets |
997 |
soundtouch::SAMPLETYPE *temp_buff = |
998 |
(soundtouch::SAMPLETYPE*)encoder->GetFrameBuffer(); |
999 |
size_t frameSize = encoder->FrameSize()/abps; |
1000 |
|
1001 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
1002 |
QString("_AddSamples Enc sfs=%1 bfs=%2 sss=%3") |
1003 |
.arg(frameSize) |
1004 |
.arg(encoder->FrameSize()) |
1005 |
.arg(pSoundStretch->numSamples())); |
1006 |
|
1007 |
// process the same number of samples as it creates |
1008 |
// a full encoded buffer just like before |
1009 |
while (pSoundStretch->numSamples() >= frameSize) |
1010 |
{ |
1011 |
int got = pSoundStretch->receiveSamples( |
1012 |
temp_buff, frameSize); |
1013 |
int amount = encoder->Encode(temp_buff); |
1014 |
|
1015 |
VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
1016 |
QString("_AddSamples Enc bytes=%1 got=%2 left=%3") |
1017 |
.arg(amount) |
1018 |
.arg(got) |
1019 |
.arg(pSoundStretch->numSamples())); |
1020 |
|
1021 |
if (!amount) |
1022 |
continue; |
1023 |
|
1024 |
//len = WaitForFreeSpace(amount); |
1025 |
char *ob = encoder->GetOutBuff(); |
1026 |
if (amount >= bdiff) |
1027 |
{ |
1028 |
memcpy(audiobuffer + org_waud, ob, bdiff); |
1029 |
ob += bdiff; |
1030 |
amount -= bdiff; |
1031 |
org_waud = 0; |
1032 |
} |
1033 |
if (amount > 0) |
1034 |
memcpy(audiobuffer + org_waud, ob, amount); |
1035 |
|
946 |
|
1036 |
bdiff = AUDBUFSIZE - amount; |
947 |
int nSamples = pSoundStretch->numSamples(); |
1037 |
org_waud += amount; |
948 |
len = WaitForFreeSpace(nSamples); |
1038 |
} |
949 |
|
1039 |
} |
950 |
while ((nSamples = pSoundStretch->numSamples())) |
1040 |
else |
951 |
{ |
1041 |
{ |
952 |
if (nSamples > nSamplesToEnd) |
1042 |
int newLen = 0; |
953 |
nSamples = nSamplesToEnd; |
1043 |
int nSamples; |
954 |
|
1044 |
len = WaitForFreeSpace(pSoundStretch->numSamples() * |
955 |
nSamples = pSoundStretch->receiveSamples( |
1045 |
audio_bytes_per_sample); |
956 |
(soundtouch::SAMPLETYPE*) |
1046 |
do |
957 |
(audiobuffer + org_waud), nSamples |
1047 |
{ |
958 |
); |
1048 |
int samplesToGet = len/audio_bytes_per_sample; |
959 |
|
1049 |
if (samplesToGet > nSamplesToEnd) |
960 |
if (nSamples == nSamplesToEnd) { |
1050 |
{ |
961 |
org_waud = 0; |
1051 |
samplesToGet = nSamplesToEnd; |
962 |
nSamplesToEnd = AUDBUFSIZE/abps; |
1052 |
} |
963 |
} |
1053 |
|
964 |
else { |
1054 |
nSamples = pSoundStretch->receiveSamples( |
965 |
org_waud += nSamples * abps; |
1055 |
(soundtouch::SAMPLETYPE*) |
966 |
nSamplesToEnd -= nSamples; |
1056 |
(audiobuffer + org_waud), samplesToGet); |
|
|
1057 |
if (nSamples == nSamplesToEnd) |
1058 |
{ |
1059 |
org_waud = 0; |
1060 |
nSamplesToEnd = AUDBUFSIZE/audio_bytes_per_sample; |
1061 |
} |
1062 |
else |
1063 |
{ |
1064 |
org_waud += nSamples * audio_bytes_per_sample; |
1065 |
nSamplesToEnd -= nSamples; |
1066 |
} |
1067 |
|
1068 |
newLen += nSamples * audio_bytes_per_sample; |
1069 |
len -= nSamples * audio_bytes_per_sample; |
1070 |
} while (nSamples > 0); |
1071 |
} |
967 |
} |
|
|
968 |
|
1072 |
} |
969 |
} |
|
|
970 |
|
971 |
} |
1073 |
|
972 |
|
1074 |
waud = org_waud; |
973 |
// Encode to AC-3? |
1075 |
lastaudiolen = audiolen(false); |
974 |
if (encoder) |
|
|
975 |
{ |
976 |
|
977 |
org_waud = waud; |
978 |
int bdiff = AUDBUFSIZE - org_waud; |
979 |
int to_get = 0; |
1076 |
|
980 |
|
1077 |
if (timecode < 0) |
981 |
if (bdiff < len) |
1078 |
{ |
982 |
{ |
1079 |
// mythmusic doesn't give timestamps.. |
983 |
encoder->Encode(audiobuffer + org_waud, bdiff); |
1080 |
timecode = (int)((samples_buffered * 100000.0) / effdsp); |
984 |
to_get = encoder->Encode(audiobuffer, len - bdiff); |
1081 |
} |
985 |
} |
|
|
986 |
else |
987 |
to_get = encoder->Encode(audiobuffer + org_waud, len); |
1082 |
|
988 |
|
1083 |
samples_buffered += samples; |
989 |
if (to_get > 0) |
1084 |
|
|
|
1085 |
/* we want the time at the end -- but the file format stores |
1086 |
time at the start of the chunk. */ |
1087 |
// even with timestretch, timecode is still calculated from original |
1088 |
// sample count |
1089 |
audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp); |
1090 |
|
1091 |
if (interleaved) |
1092 |
{ |
990 |
{ |
1093 |
dispatchVisual((unsigned char *)buffer, len, timecode, |
991 |
|
1094 |
source_audio_channels, audio_bits); |
992 |
if (to_get >= bdiff) |
|
|
993 |
{ |
994 |
encoder->GetFrames(audiobuffer + org_waud, bdiff); |
995 |
to_get -= bdiff; |
996 |
org_waud = 0; |
997 |
} |
998 |
if (to_get > 0) |
999 |
encoder->GetFrames(audiobuffer + org_waud, to_get); |
1000 |
|
1001 |
org_waud += to_get; |
1002 |
|
1095 |
} |
1003 |
} |
|
|
1004 |
|
1096 |
} |
1005 |
} |
1097 |
|
1006 |
|
1098 |
pthread_mutex_unlock(&audio_buflock); |
1007 |
waud = org_waud; |
|
|
1008 |
lastaudiolen = audiolen(false); |
1009 |
|
1010 |
if (timecode < 0) |
1011 |
// mythmusic doesn't give timestamps.. |
1012 |
timecode = (int)((samples_buffered * 100000.0) / effdsp); |
1013 |
|
1014 |
samples_buffered += samples; |
1015 |
|
1016 |
/* we want the time at the end -- but the file format stores |
1017 |
time at the start of the chunk. */ |
1018 |
// even with timestretch, timecode is still calculated from original |
1019 |
// sample count |
1020 |
audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp); |
1021 |
|
1099 |
} |
1022 |
} |
1100 |
|
1023 |
|
1101 |
void AudioOutputBase::Status() |
1024 |
void AudioOutputBase::Status() |