Mercurial > mplayer.hg
view libaf/af_delay.c @ 8389:e8c51ec86340
fixed in/out framesize rounding bug (causing low-rate QCLP hangup/looping)
disabled TerminateQTML(), as it does carshing (due to patched InitializeQTML)
author | arpi |
---|---|
date | Sat, 07 Dec 2002 02:26:45 +0000 |
parents | 1cf5d8a5bbe8 |
children | d6f40a06867b |
line wrap: on
line source
/* 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 "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_DELAY_SET_LEN,&((af_delay_t*)af->setup)->tlen); } case AF_CONTROL_COMMAND_LINE:{ float d = 0; sscanf((char*)arg,"%f",&d); return af->control(af,AF_CONTROL_DELAY_SET_LEN,&d); } case AF_CONTROL_DELAY_SET_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){ af_msg(AF_MSG_ERROR,"Error setting delay length in af_delay. Delay must be between 0s and 30s\n"); s->len=0; s->tlen=0.0; af->delay=0.0; return AF_ERROR; } // Set new len and allocate new buffer s->tlen = *((float*)arg); af->delay = s->tlen * 1000.0; // s->len = af->data->rate*af->data->bps*af->data->nch*(int)s->tlen; s->len = ((int)(af->data->rate*s->tlen))*af->data->bps*af->data->nch; s->buf = malloc(s->len); af_msg(AF_MSG_DEBUG0,"[delay] Delaying audio output by %0.2fs\n",s->tlen); af_msg(AF_MSG_DEBUG1,"[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 memmove(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", "", AF_FLAGS_REENTRANT, open };