2 * Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 // Data for specific instances of this filter
31 typedef struct af_pan_s
33 int nch
; // Number of output channels; zero means same as input
34 float level
[AF_NCH
][AF_NCH
]; // Gain level for each channel
37 // Initialization and runtime control
38 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
40 af_pan_t
* s
= af
->setup
;
43 case AF_CONTROL_REINIT
:
45 if(!arg
) return AF_ERROR
;
47 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
48 af
->data
->format
= AF_FORMAT_FLOAT_NE
;
50 af
->data
->nch
= s
->nch
? s
->nch
: ((af_data_t
*)arg
)->nch
;
51 af
->mul
= (double)af
->data
->nch
/ ((af_data_t
*)arg
)->nch
;
53 if((af
->data
->format
!= ((af_data_t
*)arg
)->format
) ||
54 (af
->data
->bps
!= ((af_data_t
*)arg
)->bps
)){
55 ((af_data_t
*)arg
)->format
= af
->data
->format
;
56 ((af_data_t
*)arg
)->bps
= af
->data
->bps
;
60 case AF_CONTROL_COMMAND_LINE
:{
65 // Read number of outputs
66 sscanf((char*)arg
,"%i%n", &nch
,&n
);
67 if(AF_OK
!= control(af
,AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
, &nch
))
71 cp
= &((char*)arg
)[n
];
73 while((*cp
== ':') && (k
< AF_NCH
)){
74 sscanf(cp
, ":%f%n" , &s
->level
[j
][k
], &n
);
75 mp_msg(MSGT_AFILTER
, MSGL_V
, "[pan] Pan level from channel %i to"
76 " channel %i = %f\n",k
,j
,s
->level
[j
][k
]);
86 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_SET
:{
88 int ch
= ((af_control_ext_t
*)arg
)->ch
;
89 float* level
= ((af_control_ext_t
*)arg
)->arg
;
93 s
->level
[ch
][i
] = level
[i
];
96 case AF_CONTROL_PAN_LEVEL
| AF_CONTROL_GET
:{
98 int ch
= ((af_control_ext_t
*)arg
)->ch
;
99 float* level
= ((af_control_ext_t
*)arg
)->arg
;
102 for(i
=0;i
<AF_NCH
;i
++)
103 level
[i
] = s
->level
[ch
][i
];
106 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_SET
:
107 // Reinit must be called after this function has been called
110 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
111 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[pan] The number of output channels must be"
112 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
115 s
->nch
=((int*)arg
)[0];
117 case AF_CONTROL_PAN_NOUT
| AF_CONTROL_GET
:
118 *(int*)arg
= af
->data
->nch
;
120 case AF_CONTROL_PAN_BALANCE
| AF_CONTROL_SET
:{
121 float val
= *(float*)arg
;
124 if (af
->data
->nch
>= 2) {
125 s
->level
[0][0] = min(1.f
, 1.f
- val
);
126 s
->level
[0][1] = max(0.f
, val
);
127 s
->level
[1][0] = max(0.f
, -val
);
128 s
->level
[1][1] = min(1.f
, 1.f
+ val
);
132 case AF_CONTROL_PAN_BALANCE
| AF_CONTROL_GET
:
135 *(float*)arg
= s
->level
[0][1] - s
->level
[1][0];
142 static void uninit(struct af_instance_s
* af
)
145 free(af
->data
->audio
);
151 // Filter data through filter
152 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
154 af_data_t
* c
= data
; // Current working data
155 af_data_t
* l
= af
->data
; // Local data
156 af_pan_t
* s
= af
->setup
; // Setup for this instance
157 float* in
= c
->audio
; // Input audio data
158 float* out
= NULL
; // Output audio data
159 float* end
= in
+c
->len
/4; // End of loop
160 int nchi
= c
->nch
; // Number of input channels
161 int ncho
= l
->nch
; // Number of output channels
164 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
172 register float x
= 0.0;
173 register float* tin
= in
;
175 x
+= tin
[k
] * s
->level
[j
][k
];
184 c
->len
= c
->len
/ c
->nch
* l
->nch
;
190 // Allocate memory and set function pointers
191 static int af_open(af_instance_t
* af
){
196 af
->data
=calloc(1,sizeof(af_data_t
));
197 af
->setup
=calloc(1,sizeof(af_pan_t
));
198 if(af
->data
== NULL
|| af
->setup
== NULL
)
203 // Description of this filter
204 af_info_t af_info_pan
= {
205 "Panning audio filter",