1 /*
2  * Copyright (C)2002 Anders Johansson ajh@atri.curtin.edu.au
3  *
4  * This file is part of MPlayer.
5  *
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.
10  *
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.
15  *
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.
19  */
20 
21 /* This audio filter changes the volume of the sound, and can be used
22    when the mixer doesn't support the PCM channel. It can handle
23    between 1 and AF_NCH channels. The volume can be adjusted between -60dB
24    to +20dB and is set on a per channels basis. The is accessed through
25    AF_CONTROL_VOLUME_LEVEL.
26 
27    The filter has support for soft-clipping, it is enabled by
28    AF_CONTROL_VOLUME_SOFTCLIPP.
29 */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <inttypes.h>
36 #include <math.h>
37 #include <limits.h>
38 
39 #include "libavutil/common.h"
40 #include "mp_msg.h"
41 #include "af.h"
42 
43 // Data for specific instances of this filter
44 typedef struct af_volume_s
45 {
46   float	max;			// Max Power level [dB]
47   float level[AF_NCH];		// Gain level for each channel
48   int soft;			// Enable/disable soft clipping
49   int fast;			// Use fix-point volume control
50 }af_volume_t;
51 
52 // Initialization and runtime control
control(struct af_instance_s * af,int cmd,void * arg)53 static int control(struct af_instance_s* af, int cmd, void* arg)
54 {
55   af_volume_t* s   = (af_volume_t*)af->setup;
56 
57   switch(cmd){
58   case AF_CONTROL_REINIT:
59     // Sanity check
60     if(!arg) return AF_ERROR;
61 
62     af->data->rate   = ((af_data_t*)arg)->rate;
63     af->data->nch    = ((af_data_t*)arg)->nch;
64 
65     if(s->fast && (((af_data_t*)arg)->format != (AF_FORMAT_FLOAT_NE))){
66       af->data->format = AF_FORMAT_S16_NE;
67       af->data->bps    = 2;
68     }
69     else{
70       af->data->format = AF_FORMAT_FLOAT_NE;
71       af->data->bps    = 4;
72     }
73     return af_test_output(af,(af_data_t*)arg);
74   case AF_CONTROL_COMMAND_LINE:{
75     float v=0.0;
76     float vol[AF_NCH];
77     int   i;
78     sscanf((char*)arg,"%f:%i", &v, &s->soft);
79     for(i=0;i<AF_NCH;i++) vol[i]=v;
80     return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol);
81   }
82   case AF_CONTROL_POST_CREATE:
83     s->fast = ((((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) ==
84       AF_INIT_FLOAT) ? 0 : 1;
85     return AF_OK;
86   case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET:
87     s->soft = *(int*)arg;
88     return AF_OK;
89   case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_GET:
90     *(int*)arg = s->soft;
91     return AF_OK;
92   case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET:
93     return af_from_dB(AF_NCH,(float*)arg,s->level,20.0,-200.0,60.0);
94   case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET:
95     return af_to_dB(AF_NCH,s->level,(float*)arg,20.0);
96   case AF_CONTROL_PRE_DESTROY:
97     if(!s->fast){
98 	float m = s->max;
99 	af_to_dB(1, &m, &m, 10.0);
100 	mp_msg(MSGT_AFILTER, MSGL_INFO, "[volume] The maximum volume was %0.2fdB \n", m);
101     }
102     return AF_OK;
103   }
104   return AF_UNKNOWN;
105 }
106 
107 // Deallocate memory
uninit(struct af_instance_s * af)108 static void uninit(struct af_instance_s* af)
109 {
110     free(af->data);
111     free(af->setup);
112 }
113 
s16_inner_loop(int16_t * data,int len,int offset,int step,float level)114 static av_always_inline void s16_inner_loop(int16_t *data, int len, int offset, int step, float level)
115 {
116   int i;
117   register int vol = (int)(255.0 * level);
118   for (i = offset; i < len; i += step)
119   {
120     register int x = (data[i] * vol) >> 8;
121     data[i] = av_clip_int16(x);
122   }
123 }
124 
float_inner_loop(float * data,int len,int offset,int step,float level,int softclip)125 static av_always_inline void float_inner_loop(float *data, int len, int offset, int step, float level, int softclip)
126 {
127   int i;
128 #if HAVE_NEON && !ARCH_AARCH64
129   if (offset == 0 && step == 1 && !softclip && len >= 8)
130   {
131     __asm__(
132       "vmov.32 d2[0], %2\n\t"
133       "vdup.32 q8, %3\n\t"
134       "vneg.f32 q9, q8\n\t"
135 "0:\n\t"
136       "vld1.32 {q0}, [%0]\n\t"
137       "vmul.f32 q0, q0, d2[0]\n\t"
138       "cmp %0, %1\n\t"
139       "vmin.f32 q0, q0, q8\n\t"
140       "vmax.f32 q0, q0, q9\n\t"
141       "vst1.32 {q0}, [%0]!\n\t"
142       "blo 0b\n\t"
143     : "+&r"(data)
144     : "r"(data + len - 7), "r"(level), "r"(0x3f800000)
145     : "cc", "q0", "d2", "q8", "q9", "memory");
146     len &= 3;
147   }
148 #endif
149   for (i = offset; i < len; i += step)
150   {
151     register float x = data[i];
152     // Set volume
153     x *= level;
154     /* Soft clipping, the sound of a dream, thanks to Jon Wattes
155        post to Musicdsp.org */
156     if (softclip)
157       x = af_softclip(x);
158     // Hard clipping
159     else
160       x = av_clipf(x,-1.0,1.0);
161     data[i] = x;
162   }
163 }
164 
165 // Filter data through filter
play(struct af_instance_s * af,af_data_t * data)166 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
167 {
168   af_data_t*    c   = data;			// Current working data
169   af_volume_t*  s   = af->setup;		// Setup for this instance
170   int           ch  = 0;			// Channel counter
171   register int	nch = c->nch;			// Number of channels
172   register int  i   = 0;
173   int same_vol = 1;
174 
175   for (ch = 1; ch < nch; ch++)
176   {
177     same_vol &= s->level[ch] == s->level[ch - 1];
178   }
179   // Basic operation volume control only (used on slow machines)
180   if(af->data->format == (AF_FORMAT_S16_NE)){
181     int16_t*    a   = (int16_t*)c->audio;	// Audio data
182     int         len = c->len/2;			// Number of samples
183     if (same_vol)
184       s16_inner_loop(a, len, 0, 1, s->level[0]);
185     else for (ch = 0; ch < nch; ch++)
186       s16_inner_loop(a, len, ch, nch, s->level[ch]);
187   }
188   // Machine is fast and data is floating point
189   else if(af->data->format == (AF_FORMAT_FLOAT_NE)){
190     float*   	a   	= (float*)c->audio;	// Audio data
191     int       	len 	= c->len/4;		// Number of samples
192     for (i = 0; !s->fast && i < len; i++)
193       // Check maximum power value
194       s->max = FFMAX(s->max, a[i] * a[i]);
195     if (same_vol && s->soft)
196       float_inner_loop(a, len, 0, 1, s->level[0], 1);
197     else if (same_vol)
198       float_inner_loop(a, len, 0, 1, s->level[0], 0);
199     else for (ch = 0; ch < nch; ch++)
200       float_inner_loop(a, len, ch, nch, s->level[ch], s->soft);
201   }
202   return c;
203 }
204 
205 // Allocate memory and set function pointers
af_open(af_instance_t * af)206 static int af_open(af_instance_t* af){
207   int i = 0;
208   af->control=control;
209   af->uninit=uninit;
210   af->play=play;
211   af->mul=1;
212   af->data=calloc(1,sizeof(af_data_t));
213   af->setup=calloc(1,sizeof(af_volume_t));
214   if(af->data == NULL || af->setup == NULL)
215     return AF_ERROR;
216   // Enable volume control and set initial volume to 0dB.
217   for(i=0;i<AF_NCH;i++){
218     ((af_volume_t*)af->setup)->level[i]  = 1.0;
219   }
220   return AF_OK;
221 }
222 
223 // Description of this filter
224 const af_info_t af_info_volume = {
225     "Volume control audio filter",
226     "volume",
227     "Anders",
228     "",
229     AF_FLAGS_NOT_REENTRANT,
230     af_open
231 };
232