Fix continuous accumulation of audio samples for big txt inputs.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -24,6 +24,8 @@ · 23 unmodified lines | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #include <flite/flite.h> | 26 | #include <flite/flite.h> |
| 27 | #include "libavutil/audio_fifo.h" | ||
| 28 | #include "libavutil/avstring.h" | ||
| 27 | #include "libavutil/channel_layout.h" | 29 | #include "libavutil/channel_layout.h" |
| 28 | #include "libavutil/file.h" | 30 | #include "libavutil/file.h" |
| 29 | #include "libavutil/opt.h" | 31 | #include "libavutil/opt.h" |
| @@ -39,11 +41,14 @@ typedef struct FliteContext { · 9 unmodified lines | |||
| 39 | char *voice_str; | 41 | char *voice_str; |
| 40 | char *textfile; | 42 | char *textfile; |
| 41 | char *text; | 43 | char *text; |
| 42 | cst_wave *wave; | 44 | char *text_p; |
| 43 | int16_t *wave_samples; | 45 | char *text_saveptr; |
| 44 | int wave_nb_samples; | 46 | int nb_channels; |
| 47 | int sample_rate; | ||
| 48 | AVAudioFifo *fifo; | ||
| 45 | int list_voices; | 49 | int list_voices; |
| 46 | cst_voice *voice; | 50 | cst_voice *voice; |
| 51 | cst_audio_streaming_info *asi; | ||
| 47 | struct voice_entry *voice_entry; | 52 | struct voice_entry *voice_entry; |
| 48 | int64_t pts; | 53 | int64_t pts; |
| 49 | int frame_nb_samples; ///< number of samples per frame | 54 | int frame_nb_samples; ///< number of samples per frame |
| @@ -140,10 +145,30 @@ static int select_voice(struct voice_entry **entry_ret, const char *voice_name, · 90 unmodified lines | |||
| 140 | return AVERROR(EINVAL); | 145 | return AVERROR(EINVAL); |
| 141 | } | 146 | } |
| 142 | 147 | ||
| 148 | static int audio_stream_chunk_by_word(const cst_wave *wave, int start, int size, | ||
| 149 | int last, cst_audio_streaming_info *asi) | ||
| 150 | { | ||
| 151 | FliteContext *flite = asi->userdata; | ||
| 152 | void *const ptr[8] = { &wave->samples[start] }; | ||
| 153 | |||
| 154 | flite->nb_channels = wave->num_channels; | ||
| 155 | flite->sample_rate = wave->sample_rate; | ||
| 156 | if (!flite->fifo) { | ||
| 157 | flite->fifo = av_audio_fifo_alloc(AV_SAMPLE_FMT_S16, flite->nb_channels, size); | ||
| 158 | if (!flite->fifo) | ||
| 159 | return CST_AUDIO_STREAM_STOP; | ||
| 160 | } | ||
| 161 | |||
| 162 | av_audio_fifo_write(flite->fifo, ptr, size); | ||
| 163 | |||
| 164 | return CST_AUDIO_STREAM_CONT; | ||
| 165 | } | ||
| 166 | |||
| 143 | static av_cold int init(AVFilterContext *ctx) | 167 | static av_cold int init(AVFilterContext *ctx) |
| 144 | { | 168 | { |
| 145 | FliteContext *flite = ctx->priv; | 169 | FliteContext *flite = ctx->priv; |
| 146 | int ret = 0; | 170 | int ret = 0; |
| 171 | char *text; | ||
| 147 | 172 | ||
| 148 | if (flite->list_voices) { | 173 | if (flite->list_voices) { |
| 149 | list_voices(ctx, "\n"); | 174 | list_voices(ctx, "\n"); |
| @@ -197,10 +222,21 @@ static av_cold int init(AVFilterContext *ctx) · 47 unmodified lines | |||
| 197 | return AVERROR(EINVAL); | 222 | return AVERROR(EINVAL); |
| 198 | } | 223 | } |
| 199 | 224 | ||
| 200 | /* synth all the file data in block */ | 225 | flite->asi = new_audio_streaming_info(); |
| 201 | flite->wave = flite_text_to_wave(flite->text, flite->voice); | 226 | if (!flite->asi) |
| 202 | flite->wave_samples = flite->wave->samples; | 227 | return AVERROR_BUG; |
| 203 | flite->wave_nb_samples = flite->wave->num_samples; | 228 | |
| 229 | flite->asi->asc = audio_stream_chunk_by_word; | ||
| 230 | flite->asi->userdata = flite; | ||
| 231 | feat_set(flite->voice->features, "streaming_info", audio_streaming_info_val(flite->asi)); | ||
| 232 | |||
| 233 | flite->text_p = flite->text; | ||
| 234 | if (!(text = av_strtok(flite->text_p, "\n", &flite->text_saveptr))) | ||
| 235 | return AVERROR(EINVAL); | ||
| 236 | flite->text_p = NULL; | ||
| 237 | |||
| 238 | flite_text_to_speech(text, flite->voice, "none"); | ||
| 239 | |||
| 204 | return 0; | 240 | return 0; |
| 205 | } | 241 | } |
| 206 | 242 | ||
| @@ -216,8 +252,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 9 unmodified lines | |||
| 216 | } | 252 | } |
| 217 | pthread_mutex_unlock(&flite_mutex); | 253 | pthread_mutex_unlock(&flite_mutex); |
| 218 | } | 254 | } |
| 219 | delete_wave(flite->wave); | 255 | av_audio_fifo_free(flite->fifo); |
| 220 | flite->wave = NULL; | ||
| 221 | } | 256 | } |
| 222 | 257 | ||
| 223 | static int query_formats(AVFilterContext *ctx) | 258 | static int query_formats(AVFilterContext *ctx) |
| @@ -230,13 +265,13 @@ static int query_formats(AVFilterContext *ctx) · 6 unmodified lines | |||
| 230 | AVFilterFormats *sample_rates = NULL; | 265 | AVFilterFormats *sample_rates = NULL; |
| 231 | AVChannelLayout chlayout = { 0 }; | 266 | AVChannelLayout chlayout = { 0 }; |
| 232 | 267 | ||
| 233 | av_channel_layout_default(&chlayout, flite->wave->num_channels); | 268 | av_channel_layout_default(&chlayout, flite->nb_channels); |
| 234 | 269 | ||
| 235 | if ((ret = ff_add_channel_layout (&chlayouts , &chlayout )) < 0 || | 270 | if ((ret = ff_add_channel_layout (&chlayouts , &chlayout )) < 0 || |
| 236 | (ret = ff_set_common_channel_layouts (ctx , chlayouts )) < 0 || | 271 | (ret = ff_set_common_channel_layouts (ctx , chlayouts )) < 0 || |
| 237 | (ret = ff_add_format (&sample_formats, AV_SAMPLE_FMT_S16 )) < 0 || | 272 | (ret = ff_add_format (&sample_formats, AV_SAMPLE_FMT_S16 )) < 0 || |
| 238 | (ret = ff_set_common_formats (ctx , sample_formats )) < 0 || | 273 | (ret = ff_set_common_formats (ctx , sample_formats )) < 0 || |
| 239 | (ret = ff_add_format (&sample_rates , flite->wave->sample_rate)) < 0 || | 274 | (ret = ff_add_format (&sample_rates , flite->sample_rate )) < 0 || |
| 240 | (ret = ff_set_common_samplerates (ctx , sample_rates )) < 0) | 275 | (ret = ff_set_common_samplerates (ctx , sample_rates )) < 0) |
| 241 | return ret; | 276 | return ret; |
| 242 | 277 | ||
| @@ -248,12 +283,13 @@ static int config_props(AVFilterLink *outlink) · 5 unmodified lines | |||
| 248 | AVFilterContext *ctx = outlink->src; | 283 | AVFilterContext *ctx = outlink->src; |
| 249 | FliteContext *flite = ctx->priv; | 284 | FliteContext *flite = ctx->priv; |
| 250 | 285 | ||
| 251 | outlink->sample_rate = flite->wave->sample_rate; | 286 | outlink->sample_rate = flite->sample_rate; |
| 252 | outlink->time_base = (AVRational){1, flite->wave->sample_rate}; | 287 | outlink->time_base = (AVRational){1, flite->sample_rate}; |
| 253 | 288 | ||
| 254 | av_log(ctx, AV_LOG_VERBOSE, "voice:%s fmt:%s sample_rate:%d\n", | 289 | av_log(ctx, AV_LOG_VERBOSE, "voice:%s fmt:%s sample_rate:%d\n", |
| 255 | flite->voice_str, | 290 | flite->voice_str, |
| 256 | av_get_sample_fmt_name(outlink->format), outlink->sample_rate); | 291 | av_get_sample_fmt_name(outlink->format), outlink->sample_rate); |
| 292 | |||
| 257 | return 0; | 293 | return 0; |
| 258 | } | 294 | } |
| 259 | 295 | ||
| @@ -261,14 +297,23 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line | |||
| 261 | { | 297 | { |
| 262 | AVFilterLink *outlink = ctx->outputs[0]; | 298 | AVFilterLink *outlink = ctx->outputs[0]; |
| 263 | FliteContext *flite = ctx->priv; | 299 | FliteContext *flite = ctx->priv; |
| 264 | int nb_samples = FFMIN(flite->wave_nb_samples, flite->frame_nb_samples); | ||
| 265 | AVFrame *samplesref; | 300 | AVFrame *samplesref; |
| 301 | int nb_samples; | ||
| 266 | 302 | ||
| 267 | if (!ff_outlink_frame_wanted(outlink)) | 303 | if (!ff_outlink_frame_wanted(outlink)) |
| 268 | return FFERROR_NOT_READY; | 304 | return FFERROR_NOT_READY; |
| 269 | 305 | ||
| 306 | nb_samples = FFMIN(av_audio_fifo_size(flite->fifo), flite->frame_nb_samples); | ||
| 270 | if (!nb_samples) { | 307 | if (!nb_samples) { |
| 271 | ff_outlink_set_status(outlink, AVERROR_EOF, flite->pts); | 308 | char *text; |
| 309 | |||
| 310 | if (!(text = av_strtok(flite->text_p, "\n", &flite->text_saveptr))) { | ||
| 311 | ff_outlink_set_status(outlink, AVERROR_EOF, flite->pts); | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | flite_text_to_speech(text, flite->voice, "none"); | ||
| 316 | ff_filter_set_ready(ctx, 100); | ||
| 272 | return 0; | 317 | return 0; |
| 273 | } | 318 | } |
| 274 | 319 | ||
| @@ -276,13 +321,12 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line | |||
| 276 | if (!samplesref) | 321 | if (!samplesref) |
| 277 | return AVERROR(ENOMEM); | 322 | return AVERROR(ENOMEM); |
| 278 | 323 | ||
| 279 | memcpy(samplesref->data[0], flite->wave_samples, | 324 | av_audio_fifo_read(flite->fifo, (void **)samplesref->extended_data, |
| 280 | nb_samples * flite->wave->num_channels * 2); | 325 | nb_samples); |
| 326 | |||
| 281 | samplesref->pts = flite->pts; | 327 | samplesref->pts = flite->pts; |
| 282 | samplesref->sample_rate = flite->wave->sample_rate; | 328 | samplesref->sample_rate = flite->sample_rate; |
| 283 | flite->pts += nb_samples; | 329 | flite->pts += nb_samples; |
| 284 | flite->wave_samples += nb_samples * flite->wave->num_channels; | ||
| 285 | flite->wave_nb_samples -= nb_samples; | ||
| 286 | 330 | ||
| 287 | return ff_filter_frame(outlink, samplesref); | 331 | return ff_filter_frame(outlink, samplesref); |
| 288 | } | 332 | } |