1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/* 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
};
|