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 //=============================================================================
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_FLOAT_NE
;
42 af
->mul
.n
= af
->data
->nch
;
43 af
->mul
.d
= ((af_data_t
*)arg
)->nch
;
44 af_frac_cancel(&af
->mul
);
46 if((af
->data
->format
!= ((af_data_t
*)arg
)->format
) ||
47 (af
->data
->bps
!= ((af_data_t
*)arg
)->bps
)){
48 ((af_data_t
*)arg
)->format
= af
->data
->format
;
49 ((af_data_t
*)arg
)->bps
= af
->data
->bps
;
52 return control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &af
->data
->nch
);
53 case AF_CONTROL_COMMAND_LINE
:{
58 // Read number of outputs
59 sscanf((char*)arg
,"%i%n", &nch
,&n
);
60 if(AF_OK
!= control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &nch
))
64 cp
= &((char*)arg
)[n
];
66 while((*cp
== ':') && (k
< AF_NCH
)){
67 sscanf(cp
, ":%f%n" , &s
->level
[j
][k
], &n
);
68 af_msg(AF_MSG_VERBOSE
,"[pan] Pan level from channel %i to"
69 " channel %i = %f\n",k
,j
,s
->level
[j
][k
]);
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
;
86 s
->level
[ch
][i
] = level
[i
];
89 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_GET
:{
91 int ch
= ((af_control_ext_t
*)arg
)->ch
;
92 float* level
= ((af_control_ext_t
*)arg
)->arg
;
96 level
[i
] = s
->level
[ch
][i
];
99 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
:
100 // Reinit must be called after this function has been called
103 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
104 af_msg(AF_MSG_ERROR
,"[pan] The number of output channels must be"
105 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
108 af
->data
->nch
=((int*)arg
)[0];
110 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_GET
:
111 *(int*)arg
= af
->data
->nch
;
118 static void uninit(struct af_instance_s
* af
)
121 free(af
->data
->audio
);
128 // Filter data through filter
129 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
131 af_data_t
* c
= data
; // Current working data
132 af_data_t
* l
= af
->data
; // Local data
133 af_pan_t
* s
= af
->setup
; // Setup for this instance
134 float* in
= c
->audio
; // Input audio data
135 float* out
= NULL
; // Output audio data
136 float* end
= in
+c
->len
/4; // End of loop
137 int nchi
= c
->nch
; // Number of input channels
138 int ncho
= l
->nch
; // Number of output channels
141 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
149 register float x
= 0.0;
150 register float* tin
= in
;
152 x
+= tin
[k
] * s
->level
[j
][k
];
161 c
->len
= (c
->len
*af
->mul
.n
)/af
->mul
.d
;
167 // Allocate memory and set function pointers
168 static int open(af_instance_t
* af
){
174 af
->data
=calloc(1,sizeof(af_data_t
));
175 af
->setup
=calloc(1,sizeof(af_pan_t
));
176 if(af
->data
== NULL
|| af
->setup
== NULL
)
178 // Set initial pan to pass-through.
182 // Description of this filter
183 af_info_t af_info_pan
= {
184 "Panning audio filter",
188 AF_FLAGS_NOT_REENTRANT
,