/** * Trivially upmixes */ static block_t *Upmix( filter_t *p_filter, block_t *p_in_buf ) { unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); assert( i_input_nb < i_output_nb ); block_t *p_out_buf = block_Alloc( p_in_buf->i_buffer * i_output_nb / i_input_nb ); if( unlikely(p_out_buf == NULL) ) { block_Release( p_in_buf ); return NULL; } p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_dts = p_in_buf->i_dts; p_out_buf->i_pts = p_in_buf->i_pts; p_out_buf->i_length = p_in_buf->i_length; float *p_dest = (float *)p_out_buf->p_buffer; const float *p_src = (float *)p_in_buf->p_buffer; for( size_t i = 0; i < p_in_buf->i_nb_samples; i++ ) { for( unsigned j = 0; j < i_output_nb; j++ ) p_dest[j] = p_src[j % i_input_nb]; p_src += i_input_nb; p_dest += i_output_nb; } block_Release( p_in_buf ); return p_out_buf; }
/** * Trivially downmixes (i.e. drop extra channels) */ static block_t *Downmix( filter_t *p_filter, block_t *p_buf ) { unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); assert( i_input_nb >= i_output_nb ); float *p_dest = (float *)p_buf->p_buffer; const float *p_src = p_dest; const int *channel_map = p_filter->p_sys->channel_map; /* Use an extra buffer to avoid overlapping */ float buffer[i_output_nb]; for( size_t i = 0; i < p_buf->i_nb_samples; i++ ) { for( unsigned j = 0; j < i_output_nb; j++ ) buffer[j] = channel_map[j] == -1 ? 0.f : p_src[channel_map[j]]; memcpy( p_dest, buffer, i_output_nb * sizeof(float) ); p_src += i_input_nb; p_dest += i_output_nb; } p_buf->i_buffer = p_buf->i_buffer * i_output_nb / i_input_nb; return p_buf; }
/***************************************************************************** * Filter: *****************************************************************************/ static bool FilterInit( filter_t *p_filter, block_t *p_block, block_t **pp_out ) { if( !p_block || !p_block->i_nb_samples ) { if( p_block ) block_Release( p_block ); return false; } size_t i_out_size = p_block->i_nb_samples * p_filter->fmt_out.audio.i_bitspersample * p_filter->fmt_out.audio.i_channels / 8; block_t *p_out = block_Alloc( i_out_size ); if( !p_out ) { msg_Warn( p_filter, "can't get output buffer" ); block_Release( p_block ); return false; } p_out->i_nb_samples = p_block->i_nb_samples; p_out->i_dts = p_block->i_dts; p_out->i_pts = p_block->i_pts; p_out->i_length = p_block->i_length; int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); p_out->i_buffer = p_block->i_buffer * i_output_nb / i_input_nb; *pp_out = p_out; return true; }
/***************************************************************************** * aout_FormatPrepare : compute the number of bytes per frame & frame length *****************************************************************************/ void aout_FormatPrepare( audio_sample_format_t * p_format ) { p_format->i_channels = aout_FormatNbChannels( p_format ); p_format->i_bitspersample = aout_BitsPerSample( p_format->i_format ); if( p_format->i_bitspersample > 0 ) { p_format->i_bytes_per_frame = ( p_format->i_bitspersample / 8 ) * aout_FormatNbChannels( p_format ); p_format->i_frame_length = 1; } }
/***************************************************************************** * Convert *****************************************************************************/ static block_t *Convert( filter_t *p_filter, block_t *p_block ) { block_t *p_out; int i_out_size; if( !p_block || !p_block->i_nb_samples ) { if( p_block ) block_Release( p_block ); return NULL; } i_out_size = p_block->i_nb_samples * p_filter->p_sys->i_bitspersample/8 * aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); p_out = block_Alloc( i_out_size ); if( !p_out ) { msg_Warn( p_filter, "can't get output buffer" ); block_Release( p_block ); return NULL; } p_out->i_nb_samples = (p_block->i_nb_samples / p_filter->p_sys->i_nb_channels) * aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); #if 0 unsigned int i_in_size = in_buf.i_nb_samples * (p_filter->p_sys->i_bitspersample/8) * aout_FormatNbChannels( &(p_filter->fmt_in.audio) ); if( (in_buf.i_buffer != i_in_size) && ((i_in_size % 32) != 0) ) /* is it word aligned?? */ { msg_Err( p_filter, "input buffer is not word aligned" ); /* Fix output buffer to be word aligned */ } #endif memset( p_out->p_buffer, 0, i_out_size ); if( p_filter->p_sys->b_downmix ) { stereo2mono_downmix( p_filter, p_block, p_out ); mono( p_filter, p_out, p_block ); } else { stereo_to_mono( p_filter, p_out, p_block ); } block_Release( p_block ); return p_out; }
static int OpenResampler (vlc_object_t *obj) { filter_t *filter = (filter_t *)obj; /* Only float->float */ if (filter->fmt_in.audio.i_format != VLC_CODEC_FL32 || filter->fmt_out.audio.i_format != VLC_CODEC_FL32 /* No channels remapping */ || filter->fmt_in.audio.i_physical_channels != filter->fmt_out.audio.i_physical_channels || filter->fmt_in.audio.i_original_channels != filter->fmt_out.audio.i_original_channels) return VLC_EGENERIC; int type = var_InheritInteger (obj, "src-converter-type"); int channels = aout_FormatNbChannels (&filter->fmt_in.audio); int err; SRC_STATE *s = src_new (type, channels, &err); if (s == NULL) { msg_Err (obj, "cannot initialize resampler: %s", src_strerror (err)); return VLC_EGENERIC; } filter->p_sys = (filter_sys_t *)s; filter->pf_audio_filter = Resample; return VLC_SUCCESS; }
static block_t *Extract( filter_t *p_filter, block_t *p_in_buf ) { size_t i_out_channels = aout_FormatNbChannels( &p_filter->fmt_out.audio ); size_t i_out_size = p_in_buf->i_nb_samples * p_filter->fmt_out.audio.i_bitspersample * i_out_channels / 8; block_t *p_out_buf = block_Alloc( i_out_size ); if( unlikely(p_out_buf == NULL) ) { block_Release( p_in_buf ); return NULL; } p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_dts = p_in_buf->i_dts; p_out_buf->i_pts = p_in_buf->i_pts; p_out_buf->i_length = p_in_buf->i_length; static const int pi_selections[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, }; static_assert(sizeof(pi_selections)/sizeof(int) == AOUT_CHAN_MAX, "channel max size mismatch!"); aout_ChannelExtract( p_out_buf->p_buffer, i_out_channels, p_in_buf->p_buffer, p_filter->fmt_in.audio.i_channels, p_in_buf->i_nb_samples, pi_selections, p_filter->fmt_out.audio.i_bitspersample ); return p_out_buf; }
/***************************************************************************** * DoWork: convert a 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 ) { int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input ); /* We start from the end because b_in_place is true */ int16_t * p_in = (int16_t *)p_in_buf->p_buffer + i - 1; float * p_out = (float *)p_out_buf->p_buffer + i - 1; while( i-- ) { #if 0 /* Slow version */ *p_out = (float)*p_in / 32768.0; #else /* This is walken's trick based on IEEE float format. On my PIII * this takes 16 seconds to perform one billion conversions, instead * of 19 seconds for the above division. */ union { float f; int32_t i; } u; u.i = *p_in + 0x43c00000; *p_out = u.f - 384.0; #endif p_in--; p_out--; } p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2; }
/***************************************************************************** * Open: open a scope effect plugin *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; galaktos_thread_t *p_thread; if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { msg_Warn( p_filter, "bad input or output format" ); return VLC_EGENERIC; } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { msg_Warn( p_filter, "input and output formats are not similar" ); return VLC_EGENERIC; } p_filter->pf_do_work = DoWork; p_filter->b_in_place = 1; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); /* Create galaktos thread */ p_sys->p_thread = p_thread = vlc_object_create( p_filter, sizeof( galaktos_thread_t ) ); vlc_object_attach( p_thread, p_this ); /* var_Create( p_thread, "galaktos-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "galaktos-width", &width ); var_Create( p_thread, "galaktos-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "galaktos-height", &height ); */ p_thread->i_cur_sample = 0; bzero( p_thread->p_data, 2*2*512 ); p_thread->i_width = 600; p_thread->i_height = 600; p_thread->b_fullscreen = 0; galaktos_init( p_thread ); p_thread->i_channels = aout_FormatNbChannels( &p_filter->input ); p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) ); if( vlc_thread_create( p_thread, "galaktos update thread", Thread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { msg_Err( p_filter, "cannot lauch galaktos thread" ); if( p_thread->psz_title ) free( p_thread->psz_title ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ static int Open( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t*)p_this; unsigned i_channels; filter_sys_t *p_sys; i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); p_sys = p_filter->p_sys = (filter_sys_t *)malloc( sizeof( *p_sys ) ); // sunqueen modify if( !p_sys ) return VLC_ENOMEM; p_sys->i_nb = var_CreateGetInteger( p_filter->p_parent, "norm-buff-size" ); p_sys->f_max = var_CreateGetFloat( p_filter->p_parent, "norm-max-level" ); if( p_sys->f_max <= 0 ) p_sys->f_max = 0.01; /* We need to store (nb_buffers+1)*nb_channels floats */ p_sys->p_last = (float *)calloc( i_channels * (p_filter->p_sys->i_nb + 2), sizeof(float) ); // sunqueen modify if( !p_sys->p_last ) { free( p_sys ); return VLC_ENOMEM; } p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; }
static int Open (vlc_object_t *obj) { aout_instance_t *aout = (aout_instance_t *)obj; aout_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; aout->output.p_sys = sys; sys->opaque = var_InheritAddress (obj, "amem-data"); sys->play = var_InheritAddress (obj, "amem-play"); sys->set_volume = var_InheritAddress (obj, "amem-set-volume"); sys->cleanup = NULL; /* defer */ if (sys->play == NULL) goto error; vlc_audio_format_cb setup = var_InheritAddress (obj, "amem-setup"); char format[5] = "S16N"; unsigned rate, channels; if (setup != NULL) { rate = aout->output.output.i_rate; channels = aout_FormatNbChannels(&aout->output.output); if (setup (&sys->opaque, format, &rate, &channels)) goto error; /* Only call this callback if setup succeeded */ sys->cleanup = var_InheritAddress (obj, "amem-cleanup"); } else { rate = var_InheritInteger (obj, "amem-rate"); channels = var_InheritInteger (obj, "amem-channels"); } if (rate == 0 || rate > 192000 || channels == 0 || channels > AOUT_CHAN_MAX) goto error; /* TODO: amem-format */ /* FIXME/TODO channel mapping */ if (strcmp(format, "S16N") || aout->output.output.i_channels != channels) { msg_Err (aout, "format not supported"); goto error; } aout->output.output.i_format = VLC_CODEC_S16N; aout->output.output.i_rate = rate; aout->output.pf_play = Play; if (sys->set_volume != NULL) aout->output.pf_volume_set = VolumeSet; else aout_VolumeSoftInit (aout); return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
static block_t *Convert( filter_t *p_filter, block_t *p_block ) { if( !p_block || !p_block->i_nb_samples ) { if( p_block ) block_Release( p_block ); return NULL; } size_t i_out_size = p_block->i_nb_samples * p_filter->fmt_out.audio.i_bitspersample/8 * aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); block_t *p_out = filter_NewAudioBuffer( p_filter, i_out_size ); if( !p_out ) { msg_Warn( p_filter, "can't get output buffer" ); block_Release( p_block ); return NULL; } p_out->i_nb_samples = p_block->i_nb_samples; p_out->i_dts = p_block->i_dts; p_out->i_pts = p_block->i_pts; p_out->i_length = p_block->i_length; DoWork( p_filter, p_block, p_out ); block_Release( p_block ); return p_out; }
/***************************************************************************** * DoWork: process samples buffer ***************************************************************************** * *****************************************************************************/ static block_t * DoWork( filter_t * p_filter, block_t * p_in_buf ) { EqzFilter( p_filter, (float*)p_in_buf->p_buffer, (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples, aout_FormatNbChannels( &p_filter->fmt_in.audio ) ); return p_in_buf; }
/***************************************************************************** * DoWork: convert a 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 ) { int32_t *p_in_orig, *p_in, *p_out = (int32_t*)p_out_buf->p_buffer; unsigned int i_nb_channels = aout_FormatNbChannels( &p_filter->input ); unsigned int i_in_nb = p_in_buf->i_nb_samples; unsigned int i_out_nb = i_in_nb * p_filter->output.i_rate / p_filter->input.i_rate; unsigned int i_sample_bytes = i_nb_channels * sizeof(int32_t); unsigned int i_out, i_chan, i_remainder = 0; /* Check if we really need to run the resampler */ if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate ) { return; } #ifdef HAVE_ALLOCA p_in = (int32_t *)alloca( p_in_buf->i_nb_bytes ); #else p_in_orig = p_in = (int32_t *)malloc( p_in_buf->i_nb_bytes ); #endif if( p_in == NULL ) { return; } p_aout->p_vlc->pf_memcpy( p_in, p_in_buf->p_buffer, p_in_buf->i_nb_bytes ); for( i_out = i_out_nb ; i_out-- ; ) { for( i_chan = i_nb_channels ; i_chan ; ) { i_chan--; p_out[i_chan] = p_in[i_chan]; } p_out += i_nb_channels; i_remainder += p_filter->input.i_rate; while( i_remainder >= p_filter->output.i_rate ) { p_in += i_nb_channels; i_remainder -= p_filter->output.i_rate; } } p_out_buf->i_nb_samples = i_out_nb; p_out_buf->i_nb_bytes = i_out_nb * i_sample_bytes; p_out_buf->start_date = p_in_buf->start_date; p_out_buf->end_date = p_out_buf->start_date + p_out_buf->i_nb_samples * 1000000 / p_filter->output.i_rate; #ifndef HAVE_ALLOCA free( p_in_orig ); #endif }
/***************************************************************************** * Create: allocate linear resampler *****************************************************************************/ static int Create( vlc_object_t *p_this ) { aout_filter_t * p_filter = (aout_filter_t *)p_this; struct filter_sys_t * p_sys; double d_factor; int i_filter_wing; if ( p_filter->input.i_rate == p_filter->output.i_rate || p_filter->input.i_format != p_filter->output.i_format || p_filter->input.i_physical_channels != p_filter->output.i_physical_channels || p_filter->input.i_original_channels != p_filter->output.i_original_channels || p_filter->input.i_format != VLC_CODEC_FL32 ) { return VLC_EGENERIC; } #if !defined( __APPLE__ ) if( !config_GetInt( p_this, "hq-resampling" ) ) { return VLC_EGENERIC; } #endif /* Allocate the memory needed to store the module's structure */ p_sys = malloc( sizeof(filter_sys_t) ); if( p_sys == NULL ) return VLC_ENOMEM; p_filter->p_sys = (struct aout_filter_sys_t *)p_sys; /* Calculate worst case for the length of the filter wing */ d_factor = (double)p_filter->output.i_rate / p_filter->input.i_rate / AOUT_MAX_INPUT_RATE; i_filter_wing = ((SMALL_FILTER_NMULT + 1)/2.0) * __MAX(1.0, 1.0/d_factor) + 10; p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) * sizeof(int32_t) * 2 * i_filter_wing; /* Allocate enough memory to buffer previous samples */ p_sys->p_buf = malloc( p_sys->i_buf_size ); if( p_sys->p_buf == NULL ) { free( p_sys ); return VLC_ENOMEM; } p_sys->i_old_wing = 0; p_sys->b_filter2 = false; /* It seams to be a good valuefor this module */ p_filter->pf_do_work = DoWork; /* We don't want a new buffer to be created because we're not sure we'll * actually need to resample anything. */ p_filter->b_in_place = true; return VLC_SUCCESS; }
/***************************************************************************** * OpenAudio *****************************************************************************/ int E_(OpenAudio) ( vlc_object_t * p_this ) { aout_instance_t * p_aout = (aout_instance_t*) p_this; p_aout->output.p_sys = (aout_sys_t*) malloc( sizeof( aout_sys_t ) ); if( p_aout->output.p_sys == NULL ) { msg_Err( p_aout, "out of memory" ); return -1; } aout_sys_t * p_sys = p_aout->output.p_sys; aout_VolumeSoftInit( p_aout ); int i_nb_channels = aout_FormatNbChannels( &p_aout->output.output ); /* BSoundPlayer does not support more than 2 channels AFAIK */ if( i_nb_channels > 2 ) { i_nb_channels = 2; p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } media_raw_audio_format * p_format; p_format = (media_raw_audio_format*) malloc( sizeof( media_raw_audio_format ) ); p_format->channel_count = i_nb_channels; p_format->frame_rate = p_aout->output.output.i_rate; p_format->format = media_raw_audio_format::B_AUDIO_FLOAT; #ifdef WORDS_BIGENDIAN p_format->byte_order = B_MEDIA_BIG_ENDIAN; #else p_format->byte_order = B_MEDIA_LITTLE_ENDIAN; #endif p_format->buffer_size = 8192; p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); p_aout->output.i_nb_samples = 2048 / i_nb_channels; p_aout->output.pf_play = DoNothing; p_sys->p_player = new BSoundPlayer( p_format, "player", Play, NULL, p_aout ); if( p_sys->p_player->InitCheck() != B_OK ) { msg_Err( p_aout, "BSoundPlayer InitCheck failed" ); delete p_sys->p_player; free( p_sys ); return -1; } /* Start playing */ p_sys->latency = p_sys->p_player->Latency(); p_sys->p_player->Start(); p_sys->p_player->SetHasData( true ); return 0; }
/***************************************************************************** * DoWork: process samples 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 ) { p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes; EqzFilter( p_aout, p_filter, (float*)p_out_buf->p_buffer, (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples, aout_FormatNbChannels( &p_filter->input ) ); }
/***************************************************************************** * DoWork: decode an MPEG audio frame. *****************************************************************************/ static void DoWork( filter_t * p_filter, block_t * p_in_buf, block_t * p_out_buf ) { filter_sys_t *p_sys = p_filter->p_sys; p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) * aout_FormatNbChannels( &p_filter->fmt_out.audio ); /* Do the actual decoding now. */ mad_stream_buffer( &p_sys->mad_stream, p_in_buf->p_buffer, p_in_buf->i_buffer ); if ( mad_frame_decode( &p_sys->mad_frame, &p_sys->mad_stream ) == -1 ) { msg_Dbg( p_filter, "libmad error: %s", mad_stream_errorstr( &p_sys->mad_stream ) ); p_sys->i_reject_count = 3; } else if( p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY ) { p_sys->i_reject_count = 3; } if( p_sys->i_reject_count > 0 ) { memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer ); p_sys->i_reject_count--; return; } mad_synth_frame( &p_sys->mad_synth, &p_sys->mad_frame ); struct mad_pcm * p_pcm = &p_sys->mad_synth.pcm; unsigned int i_samples = p_pcm->length; mad_fixed_t const * p_left = p_pcm->samples[0]; mad_fixed_t const * p_right = p_pcm->samples[1]; mad_fixed_t * p_samples = (mad_fixed_t *)p_out_buf->p_buffer; assert( i_samples == p_out_buf->i_nb_samples ); /* Interleave and keep buffers in mad_fixed_t format */ if ( p_pcm->channels == 2 ) { while ( i_samples-- ) { *p_samples++ = *p_left++; *p_samples++ = *p_right++; } } else { assert( p_pcm->channels == 1 ); memcpy( p_samples, p_left, i_samples * sizeof(mad_fixed_t) ); } }
/** * Open the module * @param p_this: the filter object * @return VLC_SUCCESS or vlc error codes */ static int Open( vlc_object_t * p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; /* Test the audio format */ if( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 || p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 ) { msg_Warn( p_filter, "bad input or output format" ); return VLC_EGENERIC; } if( !AOUT_FMTS_SIMILAR( &p_filter->fmt_in.audio, &p_filter->fmt_out.audio ) ) { msg_Warn( p_filter, "input and outut are not similar" ); return VLC_EGENERIC; } p_filter->pf_audio_filter = DoWork; p_sys = p_filter->p_sys = (filter_sys_t*)malloc( sizeof( *p_sys ) ); if( !p_sys ) return VLC_ENOMEM; /* Create the object for the thread */ vlc_sem_init( &p_sys->ready, 0 ); p_sys->b_error = false; p_sys->b_quit = false; p_sys->i_width = var_InheritInteger( p_filter, "projectm-width" ); p_sys->i_height = var_InheritInteger( p_filter, "projectm-height" ); p_sys->i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); vlc_mutex_init( &p_sys->lock ); p_sys->p_buffer = NULL; p_sys->i_buffer_size = 0; p_sys->i_nb_samples = 0; /* Create the thread */ if( vlc_clone( &p_sys->thread, Thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) goto error; vlc_sem_wait( &p_sys->ready ); if( p_sys->b_error ) { vlc_join( p_sys->thread, NULL ); goto error; } return VLC_SUCCESS; error: vlc_sem_destroy( &p_sys->ready ); free (p_sys ); return VLC_EGENERIC; }
static block_t * DoWork( filter_t * p_filter, block_t * p_in_buf ) { uint32_t nb_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); uint32_t nb_samples = p_in_buf->i_nb_samples; if ( dspCallback != 0 ) { dspCallback( ( float* )p_in_buf->p_buffer, nb_channels, nb_samples ); } return p_in_buf; }
/** * Trivially downmixes (i.e. drop extra channels) */ static block_t *Downmix( filter_t *p_filter, block_t *p_buf ) { unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); assert( i_input_nb >= i_output_nb ); float *p_dest = (float *)p_buf->p_buffer; const float *p_src = p_dest; for( size_t i = 0; i < p_buf->i_nb_samples; i++ ) { for( unsigned j = 0; j < i_output_nb; j++ ) p_dest[j] = p_src[j]; p_src += i_input_nb; p_dest += i_output_nb; } return p_buf; }
/** * Open the module. * @param p_this: the filter object * @return VLC_SUCCESS or vlc error codes */ static int Open(vlc_object_t * p_this) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; p_sys = p_filter->p_sys = (filter_sys_t*)malloc(sizeof(*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; /* Create the object for the thread */ vlc_sem_init(&p_sys->ready, 0); p_sys->b_error = false; p_sys->i_width = var_InheritInteger(p_filter, "glspectrum-width"); p_sys->i_height = var_InheritInteger(p_filter, "glspectrum-height"); p_sys->i_channels = aout_FormatNbChannels(&p_filter->fmt_in.audio); p_sys->i_prev_nb_samples = 0; p_sys->p_prev_s16_buff = NULL; p_sys->f_rotationAngle = 0; p_sys->f_rotationIncrement = ROTATION_INCREMENT; /* Fetch the FFT window parameters */ window_get_param( VLC_OBJECT( p_filter ), &p_sys->wind_param ); /* Create the FIFO for the audio data. */ p_sys->fifo = block_FifoNew(); if (p_sys->fifo == NULL) goto error; /* Create the thread */ if (vlc_clone(&p_sys->thread, Thread, p_filter, VLC_THREAD_PRIORITY_VIDEO)) goto error; /* Wait for the displaying thread to be ready. */ vlc_sem_wait(&p_sys->ready); if (p_sys->b_error) { vlc_join(p_sys->thread, NULL); goto error; } p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; error: vlc_sem_destroy(&p_sys->ready); free(p_sys); return VLC_EGENERIC; }
/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t*)p_this; bool b_fit = true; int i_channels; aout_filter_sys_t *p_sys; if( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 || p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 ) { b_fit = false; p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio.i_format = VLC_CODEC_FL32; msg_Warn( p_filter, "bad input or output format" ); } if ( !AOUT_FMTS_SIMILAR( &p_filter->fmt_in.audio, &p_filter->fmt_out.audio ) ) { b_fit = false; memcpy( &p_filter->fmt_out.audio, &p_filter->fmt_in.audio, 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 = true; i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->i_nb = var_CreateGetInteger( p_filter->p_parent, "norm-buff-size" ); p_sys->f_max = var_CreateGetFloat( p_filter->p_parent, "norm-max-level" ); if( p_sys->f_max <= 0 ) p_sys->f_max = 0.01; /* We need to store (nb_buffers+1)*nb_channels floats */ p_sys->p_last = calloc( i_channels * (p_filter->p_sys->i_nb + 2), sizeof(float) ); if( !p_sys->p_last ) { free( p_sys ); return VLC_ENOMEM; } return VLC_SUCCESS; }
/** * Open the module * @param p_this: the filter object * @return VLC_SUCCESS or vlc error codes */ static int Open( vlc_object_t * p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; /* Test the audio format */ if( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 ) { msg_Warn( p_filter, "bad input format" ); return VLC_EGENERIC; } p_sys = p_filter->p_sys = (filter_sys_t*)malloc( sizeof( *p_sys ) ); if( unlikely( !p_sys ) ) { return VLC_ENOMEM; } /* Create the object for the thread */ vlc_sem_init( &p_sys->ready, 0 ); p_sys->b_error = false; p_sys->b_quit = false; p_sys->i_width = var_InheritInteger( p_filter, "vsxu-width" ); p_sys->i_height = var_InheritInteger( p_filter, "vsxu-height" ); p_sys->i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); vlc_mutex_init( &p_sys->lock ); vlc_mutex_init( &p_sys->cyclic_block_mutex ); p_sys->vsxu_cyclic_buffer = new cyclic_block_queue(); /* Create the thread */ if( vlc_clone( &p_sys->thread, Thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) goto error; vlc_sem_wait( &p_sys->ready ); if( p_sys->b_error ) { vlc_join( p_sys->thread, NULL ); goto error; } p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; error: vlc_sem_destroy( &p_sys->ready ); free (p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Filter: *****************************************************************************/ static block_t *Filter( filter_t *p_filter, block_t *p_block ) { void (*work)(filter_t *, block_t *, block_t *) = (void *)p_filter->p_sys; if( !p_block || !p_block->i_nb_samples ) { if( p_block ) block_Release( p_block ); return NULL; } size_t i_out_size = p_block->i_nb_samples * p_filter->fmt_out.audio.i_bitspersample * p_filter->fmt_out.audio.i_channels / 8; block_t *p_out = block_Alloc( i_out_size ); if( !p_out ) { msg_Warn( p_filter, "can't get output buffer" ); block_Release( p_block ); return NULL; } p_out->i_nb_samples = p_block->i_nb_samples; p_out->i_dts = p_block->i_dts; p_out->i_pts = p_block->i_pts; p_out->i_length = p_block->i_length; int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); p_out->i_nb_samples = p_block->i_nb_samples; p_out->i_buffer = p_block->i_buffer * i_output_nb / i_input_nb; work( p_filter, p_block, p_out ); block_Release( p_block ); return p_out; }
/***************************************************************************** * Helpers: *****************************************************************************/ static bool IsSupported( const audio_format_t *p_input, const audio_format_t *p_output ) { if( p_input->i_format != VLC_CODEC_FL32 || p_input->i_format != p_output->i_format || p_input->i_rate != p_output->i_rate ) return false; if( p_input->i_physical_channels == p_output->i_physical_channels && p_input->i_original_channels == p_output->i_original_channels ) { return false; } /* Only conversion to Mono, Stereo and 4.0 right now */ if( p_output->i_physical_channels != AOUT_CHAN_CENTER && p_output->i_physical_channels != AOUT_CHANS_2_0 && p_output->i_physical_channels != AOUT_CHANS_4_0 ) { return false; } /* Only from 7/7.1/5/5.1/3/3.1/2.0 * XXX 5.X rear and middle are handled the same way */ if( (p_input->i_physical_channels & ~AOUT_CHAN_LFE) != AOUT_CHANS_7_0 && (p_input->i_physical_channels & ~AOUT_CHAN_LFE) != AOUT_CHANS_5_0 && (p_input->i_physical_channels & ~AOUT_CHAN_LFE) != AOUT_CHANS_5_0_MIDDLE && (p_input->i_physical_channels & ~AOUT_CHAN_LFE) != AOUT_CHANS_3_0 && (p_input->i_physical_channels & ~AOUT_CHAN_LFE) != AOUT_CHANS_4_CENTER_REAR && p_input->i_physical_channels != AOUT_CHANS_2_0 ) { return false; } /* Only if we downmix */ if( aout_FormatNbChannels( p_input ) <= aout_FormatNbChannels( p_output ) ) return false; return true; }
/***************************************************************************** * Open: initialize as "audio filter" *****************************************************************************/ static int Open( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; /* Allocate structure */ filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof(*p_sys) ); if( ! p_sys ) return VLC_ENOMEM; p_sys->scale = 1.0; p_sys->sample_rate = p_filter->fmt_in.audio.i_rate; p_sys->samples_per_frame = aout_FormatNbChannels( &p_filter->fmt_in.audio ); 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 = var_InheritInteger( p_this, "scaletempo-stride" ); p_sys->percent_overlap = var_InheritFloat( p_this, "scaletempo-overlap" ); p_sys->ms_search = var_InheritInteger( 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->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; } p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; aout_FormatPrepare(&p_filter->fmt_in.audio); p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; }
/** * Open the module * @param p_this: the filter object * @return VLC_SUCCESS or vlc error codes */ static int Open( vlc_object_t * p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; p_sys = p_filter->p_sys = (filter_sys_t*)malloc( sizeof( *p_sys ) ); if( unlikely( !p_sys ) ) { return VLC_ENOMEM; } /* Create the object for the thread */ p_sys->b_quit = false; p_sys->i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); vlc_mutex_init( &p_sys->lock ); vlc_mutex_init( &p_sys->cyclic_block_mutex ); p_sys->vsxu_cyclic_buffer = new cyclic_block_queue(); /* Create the openGL provider */ vout_window_cfg_t cfg; memset( &cfg, 0, sizeof(cfg) ); cfg.width = var_InheritInteger( p_filter, "vsxu-width" ); cfg.height = var_InheritInteger( p_filter, "vsxu-height" ); p_sys->gl = vlc_gl_surface_Create( VLC_OBJECT(p_filter), &cfg, NULL ); if( p_sys->gl == NULL ) goto error; /* Create the thread */ if( vlc_clone( &p_sys->thread, Thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) { vlc_gl_surface_Destroy( p_sys->gl ); goto error; } p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; return VLC_SUCCESS; error: vlc_mutex_destroy( &p_sys->cyclic_block_mutex ); vlc_mutex_destroy( &p_sys->lock ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * DoWork: convert a buffer *****************************************************************************/ static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf ) { /* Check if we really need to run the resampler */ if( p_filter->fmt_out.audio.i_rate == p_filter->fmt_in.audio.i_rate ) return p_in_buf; block_t *p_out_buf = p_in_buf; unsigned int i_out_nb = p_in_buf->i_nb_samples * p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate; const unsigned framesize = (p_filter->fmt_in.audio.i_bitspersample / 8) * aout_FormatNbChannels( &p_filter->fmt_in.audio ); if( p_filter->fmt_out.audio.i_rate > p_filter->fmt_in.audio.i_rate ) { p_out_buf = block_Alloc( i_out_nb * framesize ); if( !p_out_buf ) goto out; } unsigned char *p_out = p_out_buf->p_buffer; unsigned char *p_in = p_in_buf->p_buffer; unsigned int i_remainder = 0; p_out_buf->i_nb_samples = i_out_nb; p_out_buf->i_buffer = i_out_nb * framesize; p_out_buf->i_pts = p_in_buf->i_pts; p_out_buf->i_length = p_out_buf->i_nb_samples * 1000000 / p_filter->fmt_out.audio.i_rate; while( i_out_nb ) { if( p_out != p_in ) memcpy( p_out, p_in, framesize ); p_out += framesize; i_out_nb--; i_remainder += p_filter->fmt_in.audio.i_rate; while( i_remainder >= p_filter->fmt_out.audio.i_rate ) { p_in += framesize; i_remainder -= p_filter->fmt_out.audio.i_rate; } } if( p_in_buf != p_out_buf ) out: block_Release( p_in_buf ); return p_out_buf; }
/***************************************************************************** * OpenFilter: *****************************************************************************/ static int OpenFilter( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; /* Activate this filter only with stereo devices */ if( p_filter->fmt_out.audio.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) ) { msg_Dbg( p_filter, "filter discarded (incompatible format)" ); return VLC_EGENERIC; } /* Allocate the memory needed to store the module's structure */ p_sys = p_filter->p_sys = (filter_sys_t *)malloc( sizeof(struct filter_sys_t) ); // sunqueen modify if( p_sys == NULL ) return VLC_ENOMEM; p_sys->i_overflow_buffer_size = 0; p_sys->p_overflow_buffer = NULL; p_sys->i_nb_atomic_operations = 0; p_sys->p_atomic_operations = NULL; if( Init( VLC_OBJECT(p_filter), p_sys , aout_FormatNbChannels ( &(p_filter->fmt_in.audio) ) , p_filter->fmt_in.audio.i_physical_channels , p_filter->fmt_in.audio.i_rate ) < 0 ) { free( p_sys ); return VLC_EGENERIC; } /* Request a specific format if not already compatible */ p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio.i_format = VLC_CODEC_FL32; p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate; p_filter->fmt_in.audio.i_original_channels = p_filter->fmt_out.audio.i_original_channels; if( p_filter->fmt_in.audio.i_physical_channels == AOUT_CHANS_STEREO && (p_filter->fmt_in.audio.i_original_channels & AOUT_CHAN_DOLBYSTEREO) && !var_InheritBool( p_filter, "headphone-dolby" ) ) { p_filter->fmt_in.audio.i_physical_channels = AOUT_CHANS_5_0; } p_filter->pf_audio_filter = Convert; return VLC_SUCCESS; }