📄 scaletempo.c
字号:
*****************************************************************************/static size_t calculate_output_buffer_size( aout_filter_t *p_filter, size_t bytes_in ){ aout_filter_sys_t *p = p_filter->p_sys; size_t bytes_out = 0; int bytes_to_out = bytes_in + p->bytes_queued - p->bytes_to_slide; if( bytes_to_out >= (int)p->bytes_queue_max ) { /* while (total_buffered - stride_length * n >= queue_max) n++ */ bytes_out = p->bytes_stride * ( (unsigned)( ( bytes_to_out - p->bytes_queue_max + /* rounding protection */ p->bytes_per_frame ) / p->bytes_stride_scaled ) + 1 ); } return bytes_out;}/***************************************************************************** * reinit_buffers: reinitializes buffers in p_filter->p_sys *****************************************************************************/static int reinit_buffers( aout_filter_t *p_filter ){ aout_filter_sys_t *p = p_filter->p_sys; unsigned i,j; unsigned frames_stride = p->ms_stride * p->sample_rate / 1000.0; p->bytes_stride = frames_stride * p->bytes_per_frame; /* overlap */ unsigned frames_overlap = frames_stride * p->percent_overlap; if( frames_overlap < 1 ) { /* if no overlap */ p->bytes_overlap = 0; p->bytes_standing = p->bytes_stride; p->samples_standing = p->bytes_standing / p->bytes_per_sample; p->output_overlap = NULL; } else { unsigned prev_overlap = p->bytes_overlap; p->bytes_overlap = frames_overlap * p->bytes_per_frame; p->samples_overlap = frames_overlap * p->samples_per_frame; p->bytes_standing = p->bytes_stride - p->bytes_overlap; p->samples_standing = p->bytes_standing / p->bytes_per_sample; p->buf_overlap = malloc( p->bytes_overlap ); p->table_blend = malloc( p->samples_overlap * 4 ); /* sizeof (int32|float) */ if( !p->buf_overlap || !p->table_blend ) return VLC_ENOMEM; if( p->bytes_overlap > prev_overlap ) memset( (uint8_t *)p->buf_overlap + prev_overlap, 0, p->bytes_overlap - prev_overlap ); float *pb = p->table_blend; float t = (float)frames_overlap; for( i = 0; i<frames_overlap; i++ ) { float v = i / t; for( j = 0; j < p->samples_per_frame; j++ ) *pb++ = v; } p->output_overlap = output_overlap_float; } /* best overlap */ p->frames_search = ( frames_overlap <= 1 ) ? 0 : p->ms_search * p->sample_rate / 1000.0; if( p->frames_search < 1 ) { /* if no search */ p->best_overlap_offset = NULL; } else { unsigned bytes_pre_corr = ( p->samples_overlap - p->samples_per_frame ) * 4; /* sizeof (int32|float) */ p->buf_pre_corr = malloc( bytes_pre_corr ); p->table_window = malloc( bytes_pre_corr ); if( ! p->buf_pre_corr || ! p->table_window ) return VLC_ENOMEM; float *pw = p->table_window; for( i = 1; i<frames_overlap; i++ ) { float v = i * ( frames_overlap - i ); for( j = 0; j < p->samples_per_frame; j++ ) *pw++ = v; } p->best_overlap_offset = best_overlap_offset_float; } unsigned new_size = ( p->frames_search + frames_stride + frames_overlap ) * p->bytes_per_frame; if( p->bytes_queued > new_size ) { if( p->bytes_to_slide > p->bytes_queued ) { p->bytes_to_slide -= p->bytes_queued; p->bytes_queued = 0; } else { unsigned new_queued = __MIN( p->bytes_queued - p->bytes_to_slide, new_size ); memmove( p->buf_queue, p->buf_queue + p->bytes_queued - new_queued, new_queued ); p->bytes_to_slide = 0; p->bytes_queued = new_queued; } } p->bytes_queue_max = new_size; p->buf_queue = malloc( p->bytes_queue_max ); if( ! p->buf_queue ) return VLC_ENOMEM; p->bytes_stride_scaled = p->bytes_stride * p->scale; p->frames_stride_scaled = p->bytes_stride_scaled / p->bytes_per_frame; msg_Dbg( VLC_OBJECT(p_filter), "%.3f scale, %.3f stride_in, %i stride_out, %i standing, %i overlap, %i search, %i queue, %s mode", p->scale, p->frames_stride_scaled, (int)( p->bytes_stride / p->bytes_per_frame ), (int)( p->bytes_standing / p->bytes_per_frame ), (int)( p->bytes_overlap / p->bytes_per_frame ), p->frames_search, (int)( p->bytes_queue_max / p->bytes_per_frame ), "fl32"); return VLC_SUCCESS;}/***************************************************************************** * Open: initialize as "audio filter" *****************************************************************************/static int Open( vlc_object_t *p_this ){ aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; bool b_fit = true; if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { b_fit = false; p_filter->input.i_format = p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); msg_Warn( p_filter, "bad input or output format" ); } if( ! AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { b_fit = false; memcpy( &p_filter->output, &p_filter->input, sizeof(audio_sample_format_t) ); msg_Warn( p_filter, "input and output formats are not similar" ); } if( ! b_fit ) return VLC_EGENERIC; p_filter->pf_do_work = DoWork; p_filter->b_in_place = false; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof(aout_filter_sys_t) ); if( ! p_sys ) return VLC_ENOMEM; p_sys->scale = 1.0; p_sys->sample_rate = p_filter->input.i_rate; p_sys->samples_per_frame = aout_FormatNbChannels( &p_filter->input ); p_sys->bytes_per_sample = 4; p_sys->bytes_per_frame = p_sys->samples_per_frame * p_sys->bytes_per_sample; msg_Dbg( p_this, "format: %5i rate, %i nch, %i bps, %s", p_sys->sample_rate, p_sys->samples_per_frame, p_sys->bytes_per_sample, "fl32" ); p_sys->ms_stride = config_GetInt( p_this, "scaletempo-stride" ); p_sys->percent_overlap = config_GetFloat( p_this, "scaletempo-overlap" ); p_sys->ms_search = config_GetInt( p_this, "scaletempo-search" ); msg_Dbg( p_this, "params: %i stride, %.3f overlap, %i search", p_sys->ms_stride, p_sys->percent_overlap, p_sys->ms_search ); p_sys->i_buf = 0; p_sys->p_buffers[0] = NULL; p_sys->p_buffers[1] = NULL; p_sys->buf_queue = NULL; p_sys->buf_overlap = NULL; p_sys->table_blend = NULL; p_sys->buf_pre_corr = NULL; p_sys->table_window = NULL; p_sys->bytes_overlap = 0; p_sys->bytes_queued = 0; p_sys->bytes_to_slide = 0; p_sys->frames_stride_error = 0; if( reinit_buffers( p_filter ) != VLC_SUCCESS ) { Close( p_this ); return VLC_EGENERIC; } return VLC_SUCCESS;}static void Close( vlc_object_t *p_this ){ aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys = p_filter->p_sys; free( p_sys->buf_queue ); free( p_sys->buf_overlap ); free( p_sys->table_blend ); free( p_sys->buf_pre_corr ); free( p_sys->table_window ); free( p_sys->p_buffers[0] ); free( p_sys->p_buffers[1] ); free( p_filter->p_sys );}/***************************************************************************** * DoWork: aout_filter wrapper for transform_buffer *****************************************************************************/static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ){ VLC_UNUSED(p_aout); aout_filter_sys_t *p = p_filter->p_sys; if( p_filter->input.i_rate == p->sample_rate ) { memcpy( p_out_buf->p_buffer, p_in_buf->p_buffer, p_in_buf->i_nb_bytes ); p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes; p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; return; } double scale = p_filter->input.i_rate / (double)p->sample_rate; if( scale != p->scale ) { p->scale = scale; p->bytes_stride_scaled = p->bytes_stride * p->scale; p->frames_stride_scaled = p->bytes_stride_scaled / p->bytes_per_frame; p->bytes_to_slide = 0; msg_Dbg( p_filter, "%.3f scale, %.3f stride_in, %i stride_out", p->scale, p->frames_stride_scaled, (int)( p->bytes_stride / p->bytes_per_frame ) ); } size_t i_outsize = calculate_output_buffer_size ( p_filter, p_in_buf->i_nb_bytes ); if( i_outsize > p_out_buf->i_size ) { void *temp = realloc( p->p_buffers[ p->i_buf ], i_outsize ); if( temp == NULL ) { return; } p->p_buffers[ p->i_buf ] = temp; p_out_buf->p_buffer = p->p_buffers[ p->i_buf ]; p->i_buf = ! p->i_buf; } size_t bytes_out = transform_buffer( p_filter, p_in_buf->p_buffer, p_in_buf->i_nb_bytes, p_out_buf->p_buffer ); p_out_buf->i_nb_bytes = bytes_out; p_out_buf->i_nb_samples = bytes_out / p->bytes_per_frame;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -