diff options
author | anders <anders@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-10-01 06:45:08 +0000 |
---|---|---|
committer | anders <anders@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-10-01 06:45:08 +0000 |
commit | 1f6c494641c4ca99eec7a9f47818526c72789439 (patch) | |
tree | 17bf220c1c1ac1144dfa8212f09444e51c248a26 /libaf/af_delay.c | |
parent | c0091278d8f15580eecebfc8c454fba250cf4b94 (diff) | |
download | mpv-1f6c494641c4ca99eec7a9f47818526c72789439.tar.bz2 mpv-1f6c494641c4ca99eec7a9f47818526c72789439.tar.xz |
Adding new audio output filter layer libaf
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7569 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libaf/af_delay.c')
-rw-r--r-- | libaf/af_delay.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/libaf/af_delay.c b/libaf/af_delay.c new file mode 100644 index 0000000000..d25e6ed7f2 --- /dev/null +++ b/libaf/af_delay.c @@ -0,0 +1,146 @@ +/* This audio filter doesn't really do anything useful but serves an + example of how audio filters work. It delays the output signal by + the number of seconds set by delay=n where n is the number of + seconds. +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../config.h" +#include "../mp_msg.h" + +#include "af.h" + +// Data for specific instances of this filter +typedef struct af_delay_s +{ + void* buf; // data block used for delaying audio signal + int len; // local buffer length + float tlen; // Delay in seconds +}af_delay_t; + +// Initialization and runtime control +static int control(struct af_instance_s* af, int cmd, void* arg) +{ + switch(cmd){ + case AF_CONTROL_REINIT:{ + af->data->rate = ((af_data_t*)arg)->rate; + af->data->nch = ((af_data_t*)arg)->nch; + af->data->format = ((af_data_t*)arg)->format; + af->data->bps = ((af_data_t*)arg)->bps; + + return af->control(af,AF_CONTROL_SET_DELAY_LEN,&((af_delay_t*)af->setup)->tlen); + } + case AF_CONTROL_SET_DELAY_LEN:{ + af_delay_t* s = (af_delay_t*)af->setup; + void* bt = s->buf; // Old buffer + int lt = s->len; // Old len + + if(*((float*)arg) > 30 || *((float*)arg) < 0){ + mp_msg(MSGT_AFILTER,MSGL_ERR,"Error setting delay length in af_delay. Delay must be between 0s and 30s\n"); + s->len=0; + s->tlen=0.0; + return AF_ERROR; + } + + // Set new len and allocate new buffer + s->tlen = *((float*)arg); + s->len = af->data->rate*af->data->bps*af->data->nch*(int)s->tlen; + s->buf = malloc(s->len); + mp_msg(MSGT_AFILTER,MSGL_DBG2,"[delay] Delaying audio output by %0.2fs\n",s->tlen); + mp_msg(MSGT_AFILTER,MSGL_DBG3,"[delay] Delaying audio output by %i bytes\n",s->len); + + // Out of memory error + if(!s->buf){ + s->len = 0; + free(bt); + return AF_ERROR; + } + + // Clear the new buffer + memset(s->buf, 0, s->len); + + /* Copy old buffer to avoid click in output + sound (at least most of it) and release it */ + if(bt){ + memcpy(s->buf,bt,min(lt,s->len)); + free(bt); + } + return AF_OK; + } + } + return AF_UNKNOWN; +} + +// Deallocate memory +static void uninit(struct af_instance_s* af) +{ + if(af->data->audio) + free(af->data->audio); + if(af->data) + free(af->data); + if(((af_delay_t*)(af->setup))->buf) + free(((af_delay_t*)(af->setup))->buf); + if(af->setup) + free(af->setup); +} + +// Filter data through filter +static af_data_t* play(struct af_instance_s* af, af_data_t* data) +{ + af_data_t* c = data; // Current working data + af_data_t* l = af->data; // Local data + af_delay_t* s = (af_delay_t*)af->setup; // Setup for this instance + + + if(AF_OK != RESIZE_LOCAL_BUFFER(af , data)) + return NULL; + + if(s->len > c->len){ // Delay bigger than buffer + // Copy beginning of buffer to beginning of output buffer + memcpy(l->audio,s->buf,c->len); + // Move buffer left + memcpy(s->buf,s->buf+c->len,s->len-c->len); + // Save away current audio to end of buffer + memcpy(s->buf+s->len-c->len,c->audio,c->len); + } + else{ + // Copy end of previous block to beginning of output buffer + memcpy(l->audio,s->buf,s->len); + // Copy current block except end + memcpy(l->audio+s->len,c->audio,c->len-s->len); + // Save away end of current block for next call + memcpy(s->buf,c->audio+c->len-s->len,s->len); + } + + // Set output data + c->audio=l->audio; + + return c; +} + +// Allocate memory and set function pointers +static int open(af_instance_t* af){ + af->control=control; + af->uninit=uninit; + af->play=play; + af->mul.n=1; + af->mul.d=1; + af->data=calloc(1,sizeof(af_data_t)); + af->setup=calloc(1,sizeof(af_delay_t)); + if(af->data == NULL || af->setup == NULL) + return AF_ERROR; + return AF_OK; +} + +// Description of this filter +af_info_t af_info_delay = { + "Delay audio filter", + "delay", + "Anders", + "", + open +}; + + |