1 /*=============================================================================
3 // This software has been released under the terms of the GNU Public
4 // license. See http://www.gnu.org/copyleft/gpl.html for details.
6 // Copyright 2002 Anders Johansson ajh@atri.curtin.edu.au
8 //=============================================================================
23 // Data for specific instances of this filter
24 typedef struct af_pan_s
26 float level
[AF_NCH
][AF_NCH
]; // Gain level for each channel
29 // Initialization and runtime control
30 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
32 af_pan_t
* s
= af
->setup
;
35 case AF_CONTROL_REINIT
:
37 if(!arg
) return AF_ERROR
;
39 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
40 af
->data
->format
= AF_FORMAT_F
| AF_FORMAT_NE
;
42 af
->mul
.n
= af
->data
->nch
;
43 af
->mul
.d
= ((af_data_t
*)arg
)->nch
;
45 if((af
->data
->format
!= ((af_data_t
*)arg
)->format
) ||
46 (af
->data
->bps
!= ((af_data_t
*)arg
)->bps
)){
47 ((af_data_t
*)arg
)->format
= af
->data
->format
;
48 ((af_data_t
*)arg
)->bps
= af
->data
->bps
;
51 return control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &af
->data
->nch
);
52 case AF_CONTROL_COMMAND_LINE
:{
57 // Read number of outputs
58 sscanf((char*)arg
,"%i%n", &nch
,&n
);
59 if(AF_OK
!= control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &nch
))
63 cp
= &((char*)arg
)[n
];
65 while((*cp
== ':') && (k
< AF_NCH
)){
66 sscanf(cp
, ":%f%n" , &s
->level
[k
][j
], &n
);
67 s
->level
[k
][j
] = clamp(s
->level
[k
][j
],0.0,1.0);
68 af_msg(AF_MSG_VERBOSE
,"[pan] Pan level from channel %i to"
69 " channel %i = %f\n",j
,k
,s
->level
[k
][j
]);
79 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_SET
:{
81 int ch
= ((af_control_ext_t
*)arg
)->ch
;
82 float* level
= ((af_control_ext_t
*)arg
)->arg
;
84 s
->level
[ch
][i
] = clamp(level
[i
],0.0,1.0);
87 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_GET
:{
89 int ch
= ((af_control_ext_t
*)arg
)->ch
;
90 float* level
= ((af_control_ext_t
*)arg
)->arg
;
92 level
[i
] = s
->level
[ch
][i
];
95 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
:
96 // Reinit must be called after this function has been called
99 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
100 af_msg(AF_MSG_ERROR
,"[pan] The number of output channels must be"
101 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
104 af
->data
->nch
=((int*)arg
)[0];
106 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_GET
:
107 *(int*)arg
= af
->data
->nch
;
114 static void uninit(struct af_instance_s
* af
)
117 free(af
->data
->audio
);
124 // Filter data through filter
125 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
127 af_data_t
* c
= data
; // Current working data
128 af_data_t
* l
= af
->data
; // Local data
129 af_pan_t
* s
= af
->setup
; // Setup for this instance
130 float* in
= c
->audio
; // Input audio data
131 float* out
= NULL
; // Output audio data
132 float* end
= in
+c
->len
/4; // End of loop
133 int nchi
= c
->nch
; // Number of input channels
134 int ncho
= l
->nch
; // Number of output channels
137 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
145 register float x
= 0.0;
146 register float* tin
= in
;
148 x
+= tin
[k
] * s
->level
[j
][k
];
157 c
->len
= (c
->len
*af
->mul
.n
)/af
->mul
.d
;
163 // Allocate memory and set function pointers
164 static int open(af_instance_t
* af
){
170 af
->data
=calloc(1,sizeof(af_data_t
));
171 af
->setup
=calloc(1,sizeof(af_pan_t
));
172 if(af
->data
== NULL
|| af
->setup
== NULL
)
174 // Set initial pan to pass-through.
178 // Description of this filter
179 af_info_t af_info_pan
= {
180 "Panning audio filter",
184 AF_FLAGS_NOT_REENTRANT
,