diff options
author | Peter Schlaile <peter@schlaile.de> | 2009-06-01 20:35:05 +0400 |
---|---|---|
committer | Peter Schlaile <peter@schlaile.de> | 2009-06-01 20:35:05 +0400 |
commit | 2a3627e338516646d3e68f4db6147a80410bcf1f (patch) | |
tree | ff4008e2a7d15a79580419c3bb9835e2c418703c /source | |
parent | af42ee43be7845870655f26e26b6838c396377ba (diff) |
== Sequencer ==
This fixes:
[#18507] Wrong audio mixdown
Also: you can change output sample rate while blender is running
and the audio device get's reopened automatically.
Subframe-precision seeking was also broken for some releases...
(shame on me)
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/src/hddaudio.c | 179 | ||||
-rw-r--r-- | source/blender/src/seqaudio.c | 16 |
2 files changed, 116 insertions, 79 deletions
diff --git a/source/blender/src/hddaudio.c b/source/blender/src/hddaudio.c index 7175f140b09..bfddd29b198 100644 --- a/source/blender/src/hddaudio.c +++ b/source/blender/src/hddaudio.c @@ -216,6 +216,97 @@ long sound_hdaudio_get_duration(struct hdaudio * hdaudio, double frame_rate) } #ifdef WITH_FFMPEG + +#define RESAMPLE_FILL_RATIO (7.0/4.0) + +static void sound_hdaudio_run_resampler_seek( + struct hdaudio * hdaudio) +{ + int in_frame_size = (long long) hdaudio->sample_rate + * hdaudio->frame_duration / AV_TIME_BASE; + + hdaudio->resample_samples_in = in_frame_size * RESAMPLE_FILL_RATIO; + hdaudio->resample_samples_written + = audio_resample(hdaudio->resampler, + hdaudio->resample_cache, + hdaudio->decode_cache_zero, + in_frame_size * RESAMPLE_FILL_RATIO); +} + +static void sound_hdaudio_run_resampler_continue( + struct hdaudio * hdaudio) +{ + int target_rate = hdaudio->target_rate; + int target_channels = hdaudio->target_channels; + + int frame_size = (long long) target_rate + * hdaudio->frame_duration / AV_TIME_BASE; + int in_frame_size = (long long) hdaudio->sample_rate + * hdaudio->frame_duration / AV_TIME_BASE; + + int reuse_tgt = (hdaudio->resample_samples_written + - frame_size) * target_channels; + int reuse_src = (hdaudio->resample_samples_in + - in_frame_size) * hdaudio->channels; + int next_samples_in = + in_frame_size * RESAMPLE_FILL_RATIO + - reuse_src / hdaudio->channels; + + memmove(hdaudio->resample_cache, + hdaudio->resample_cache + frame_size * target_channels, + reuse_tgt * sizeof(short)); + + hdaudio->resample_samples_written + = audio_resample( + hdaudio->resampler, + hdaudio->resample_cache + reuse_tgt, + hdaudio->decode_cache_zero + reuse_src, + next_samples_in) + + reuse_tgt / target_channels; + + hdaudio->resample_samples_in = next_samples_in + + reuse_src / hdaudio->channels; +} + +static void sound_hdaudio_init_resampler( + struct hdaudio * hdaudio, + int frame_position, int target_rate, int target_channels) +{ + int frame_size = (long long) target_rate + * hdaudio->frame_duration / AV_TIME_BASE; + + if (hdaudio->resampler && + (hdaudio->target_rate != target_rate + || hdaudio->target_channels != target_channels)) { + audio_resample_close(hdaudio->resampler); + hdaudio->resampler = 0; + } + if (!hdaudio->resampler) { + hdaudio->resampler = av_audio_resample_init( + target_channels, hdaudio->channels, + target_rate, hdaudio->sample_rate, + SAMPLE_FMT_S16, SAMPLE_FMT_S16, + 16, 10, 0, 0.8); + hdaudio->target_rate = target_rate; + hdaudio->target_channels = target_channels; + if (hdaudio->resample_cache) { + MEM_freeN(hdaudio->resample_cache); + } + + + hdaudio->resample_cache = (short*) MEM_mallocN( + (long long) + hdaudio->target_channels + * frame_size * 2 + * sizeof(short), + "hdaudio resample cache"); + if (frame_position == hdaudio->frame_position || + frame_position == hdaudio->frame_position + 1) { + sound_hdaudio_run_resampler_seek(hdaudio); + } + } +} + static void sound_hdaudio_extract_small_block( struct hdaudio * hdaudio, short * target_buffer, @@ -240,40 +331,9 @@ static void sound_hdaudio_extract_small_block( if (hdaudio == 0) return; if (rate_conversion) { - if (hdaudio->resampler && - (hdaudio->target_rate != target_rate - || hdaudio->target_channels != target_channels)) { - audio_resample_close(hdaudio->resampler); - hdaudio->resampler = 0; - } - if (!hdaudio->resampler) { - hdaudio->resampler = audio_resample_init( - target_channels, hdaudio->channels, - target_rate, hdaudio->sample_rate); - hdaudio->target_rate = target_rate; - hdaudio->target_channels = target_channels; - if (hdaudio->resample_cache) { - MEM_freeN(hdaudio->resample_cache); - } - - - hdaudio->resample_cache = (short*) MEM_mallocN( - (long long) - hdaudio->target_channels - * frame_size * 2 - * sizeof(short), - "hdaudio resample cache"); - if (frame_position == hdaudio->frame_position) { - hdaudio->resample_samples_in = - in_frame_size * 7 / 4; - hdaudio->resample_samples_written - = audio_resample( - hdaudio->resampler, - hdaudio->resample_cache, - hdaudio->decode_cache_zero, - in_frame_size * 7 / 4); - } - } + sound_hdaudio_init_resampler( + hdaudio, frame_position, + target_rate, target_channels); } if (frame_position == hdaudio->frame_position + 1 @@ -347,36 +407,11 @@ static void sound_hdaudio_extract_small_block( } } + hdaudio->decode_pos = decode_pos; + if (rate_conversion) { - int written = hdaudio->resample_samples_written - * target_channels; - int ofs = target_channels * frame_size; - int recycle = written - ofs; - int next_in = in_frame_size - + (3.0/4.0 - - (double) recycle / (double) - (frame_size * target_channels) - ) * in_frame_size; - - memmove(hdaudio->resample_cache, - hdaudio->resample_cache + ofs, - recycle * sizeof(short)); - - hdaudio->resample_samples_written - = audio_resample( - hdaudio->resampler, - hdaudio->resample_cache + recycle, - hdaudio->decode_cache_zero - + hdaudio->resample_samples_in - * hdaudio->channels - - bl_size, - next_in) - + recycle / target_channels; - - hdaudio->resample_samples_in = next_in; + sound_hdaudio_run_resampler_continue(hdaudio); } - - hdaudio->decode_pos = decode_pos; } if (frame_position != hdaudio->frame_position) { @@ -390,6 +425,7 @@ static void sound_hdaudio_extract_small_block( * hdaudio->frame_duration / AV_TIME_BASE; long long seek_pos; + int decode_cache_zero_init = 0; hdaudio->frame_position = frame_position; @@ -435,8 +471,7 @@ static void sound_hdaudio_extract_small_block( audio_pkt_data = packet.data; audio_pkt_size = packet.size; - if (!hdaudio->decode_cache_zero - && audio_pkt_size > 0) { + if (!decode_cache_zero_init && audio_pkt_size > 0) { long long diff; if (packet.pts == AV_NOPTS_VALUE) { @@ -476,6 +511,7 @@ static void sound_hdaudio_extract_small_block( hdaudio->decode_cache_zero = hdaudio->decode_cache + diff; + decode_cache_zero_init = 1; } while (audio_pkt_size > 0) { @@ -514,22 +550,18 @@ static void sound_hdaudio_extract_small_block( break; } } + hdaudio->decode_pos = decode_pos; + if (rate_conversion) { - hdaudio->resample_samples_written - = audio_resample(hdaudio->resampler, - hdaudio->resample_cache, - hdaudio->decode_cache_zero, - in_frame_size * 7 / 4); - hdaudio->resample_samples_in = - in_frame_size * 7 / 4; + sound_hdaudio_run_resampler_seek(hdaudio); } - hdaudio->decode_pos = decode_pos; } memcpy(target_buffer, (rate_conversion ? hdaudio->resample_cache : hdaudio->decode_cache_zero) + sample_ofs, nb_samples * target_channels * sizeof(short)); + } #endif @@ -575,6 +607,9 @@ void sound_close_hdaudio(struct hdaudio * hdaudio) avcodec_close(hdaudio->pCodecCtx); av_close_input_file(hdaudio->pFormatCtx); MEM_freeN (hdaudio->decode_cache); + if (hdaudio->resampler) { + audio_resample_close(hdaudio->resampler); + } if (hdaudio->resample_cache) { MEM_freeN(hdaudio->resample_cache); } diff --git a/source/blender/src/seqaudio.c b/source/blender/src/seqaudio.c index e01928c7aee..03885292dfd 100644 --- a/source/blender/src/seqaudio.c +++ b/source/blender/src/seqaudio.c @@ -564,7 +564,7 @@ static int audio_init(SDL_AudioSpec *desired) obtained = (SDL_AudioSpec*)MEM_mallocN(sizeof(SDL_AudioSpec), "SDL_AudioSpec"); - + audio_initialised = 0; desired->callback=audio_fill; if ( SDL_OpenAudio(desired, obtained) < 0 ) { @@ -670,16 +670,18 @@ void audiostream_play(int startframe, uint32_t duration, int mixdown) sound_init_audio(); } - if (U.mixbufsize && !audio_initialised && !mixdown) { + if (U.mixbufsize && + (!audio_initialised + || desired.freq != audio_scene->audio.mixrate + || desired.samples != U.mixbufsize) + && !mixdown) { desired.freq=audio_scene->audio.mixrate; desired.format=AUDIO_S16SYS; desired.channels=2; desired.samples=U.mixbufsize; desired.userdata=0; - if (audio_init(&desired)==0) { - U.mixbufsize = 0; /* no audio */ - } + audio_init(&desired); } audio_startframe = startframe; @@ -706,7 +708,7 @@ void audiostream_start(int frame) void audiostream_scrub(int frame) { - if (U.mixbufsize) audiostream_play(frame, 4096, 0); + audiostream_play(frame, 4096, 0); } void audiostream_stop(void) @@ -721,7 +723,7 @@ int audiostream_pos(void) { int pos; - if (U.mixbufsize && audio_scene) { + if (audio_initialised && audio_scene) { pos = (int) (((double)(audio_pos-U.mixbufsize) / ( audio_scene->audio.mixrate*4 )) * FPS ); |