1 /*=============================================================================
3 // This software has been released under the terms of the GNU General Public
4 // license. See http://www.gnu.org/copyleft/gpl.html for details.
6 // Copyright 2002 Anders Johansson ajh@atri.curtin.edu.au
8 //=============================================================================
22 // Data for specific instances of this filter
23 typedef struct af_pan_s
25 int nch
; // Number of output channels; zero means same as input
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_FLOAT_NE
;
42 af
->data
->nch
= s
->nch
? s
->nch
: ((af_data_t
*)arg
)->nch
;
43 af
->mul
.n
= af
->data
->nch
;
44 af
->mul
.d
= ((af_data_t
*)arg
)->nch
;
45 af_frac_cancel(&af
->mul
);
47 if((af
->data
->format
!= ((af_data_t
*)arg
)->format
) ||
48 (af
->data
->bps
!= ((af_data_t
*)arg
)->bps
)){
49 ((af_data_t
*)arg
)->format
= af
->data
->format
;
50 ((af_data_t
*)arg
)->bps
= af
->data
->bps
;
54 case AF_CONTROL_COMMAND_LINE
:{
59 // Read number of outputs
60 sscanf((char*)arg
,"%i%n", &nch
,&n
);
61 if(AF_OK
!= control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &nch
))
65 cp
= &((char*)arg
)[n
];
67 while((*cp
== ':') && (k
< AF_NCH
)){
68 sscanf(cp
, ":%f%n" , &s
->level
[j
][k
], &n
);
69 af_msg(AF_MSG_VERBOSE
,"[pan] Pan level from channel %i to"
70 " channel %i = %f\n",k
,j
,s
->level
[j
][k
]);
80 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_SET
:{
82 int ch
= ((af_control_ext_t
*)arg
)->ch
;
83 float* level
= ((af_control_ext_t
*)arg
)->arg
;
87 s
->level
[ch
][i
] = level
[i
];
90 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_GET
:{
92 int ch
= ((af_control_ext_t
*)arg
)->ch
;
93 float* level
= ((af_control_ext_t
*)arg
)->arg
;
97 level
[i
] = s
->level
[ch
][i
];
100 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
:
101 // Reinit must be called after this function has been called
104 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
105 af_msg(AF_MSG_ERROR
,"[pan] The number of output channels must be"
106 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
109 s
->nch
=((int*)arg
)[0];
111 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_GET
:
112 *(int*)arg
= af
->data
->nch
;
114 case AF_CONTROL_PAN_BALANCE
| AF_CONTROL_SET
:{
115 float val
= *(float*)arg
;
118 if (af
->data
->nch
>= 2) {
119 s
->level
[0][0] = min(1.f
, 1.f
- val
);
120 s
->level
[0][1] = max(0.f
, val
);
121 s
->level
[1][0] = max(0.f
, -val
);
122 s
->level
[1][1] = min(1.f
, 1.f
+ val
);
126 case AF_CONTROL_PAN_BALANCE
| AF_CONTROL_GET
:
129 *(float*)arg
= s
->level
[0][1] - s
->level
[1][0];
136 static void uninit(struct af_instance_s
* af
)
139 free(af
->data
->audio
);
145 // Filter data through filter
146 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
148 af_data_t
* c
= data
; // Current working data
149 af_data_t
* l
= af
->data
; // Local data
150 af_pan_t
* s
= af
->setup
; // Setup for this instance
151 float* in
= c
->audio
; // Input audio data
152 float* out
= NULL
; // Output audio data
153 float* end
= in
+c
->len
/4; // End of loop
154 int nchi
= c
->nch
; // Number of input channels
155 int ncho
= l
->nch
; // Number of output channels
158 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
166 register float x
= 0.0;
167 register float* tin
= in
;
169 x
+= tin
[k
] * s
->level
[j
][k
];
178 c
->len
= (c
->len
*af
->mul
.n
)/af
->mul
.d
;
184 // Allocate memory and set function pointers
185 static int af_open(af_instance_t
* af
){
191 af
->data
=calloc(1,sizeof(af_data_t
));
192 af
->setup
=calloc(1,sizeof(af_pan_t
));
193 if(af
->data
== NULL
|| af
->setup
== NULL
)
198 // Description of this filter
199 af_info_t af_info_pan
= {
200 "Panning audio filter",