summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libaf/Makefile4
-rw-r--r--libaf/af.c124
-rw-r--r--libaf/af.h65
-rw-r--r--libaf/af_channels.c9
-rw-r--r--libaf/af_delay.c9
-rw-r--r--libaf/af_dummy.c7
-rw-r--r--libaf/af_equalizer.c19
-rw-r--r--libaf/af_format.c557
-rw-r--r--libaf/af_format.h32
-rw-r--r--libaf/af_format_alaw.c315
-rw-r--r--libaf/af_format_ulaw.c828
-rw-r--r--libaf/af_mp.c41
-rw-r--r--libaf/af_mp.h26
-rw-r--r--libaf/af_resample.c19
-rw-r--r--libaf/af_volume.c75
-rw-r--r--libaf/config.h15
-rw-r--r--libmpcodecs/dec_audio.c6
17 files changed, 1799 insertions, 352 deletions
diff --git a/libaf/Makefile b/libaf/Makefile
index 381d9fcf1b..05aac6d3cb 100644
--- a/libaf/Makefile
+++ b/libaf/Makefile
@@ -2,7 +2,7 @@ include ../config.mak
LIBNAME = libaf.a
-SRCS=af.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c
+SRCS=af.c af_mp.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c
OBJS=$(SRCS:.c=.o)
@@ -15,7 +15,7 @@ CFLAGS = $(OPTFLAGS) -I. -Wall
$(LIBNAME): $(OBJS) Makefile
$(AR) r $(LIBNAME) $(OBJS)
-$(OBJS):af.h control.h dsp.h filter.h window.h
+$(OBJS):af.h control.h dsp.h filter.h window.h af_mp.h
all: $(LIBNAME)
diff --git a/libaf/af.c b/libaf/af.c
index 63cb692bad..5216c6dcdb 100644
--- a/libaf/af.c
+++ b/libaf/af.c
@@ -6,9 +6,6 @@
#include <malloc.h>
#endif
-#include "../config.h"
-#include "../mp_msg.h"
-
#include "af.h"
// Static list of filters
@@ -31,6 +28,12 @@ static af_info_t* filter_list[]={ \
NULL \
};
+// Message printing
+af_msg_cfg_t af_msg_cfg={0,NULL,NULL};
+
+// CPU speed
+int* af_cpu_speed = NULL;
+
/* Find a filter in the static list of filters using it's name. This
function is used internally */
af_info_t* af_find(char*name)
@@ -41,7 +44,7 @@ af_info_t* af_find(char*name)
return filter_list[i];
i++;
}
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't find audio filter '%s'\n",name);
+ af_msg(AF_MSG_ERROR,"Couldn't find audio filter '%s'\n",name);
return NULL;
}
@@ -69,7 +72,7 @@ af_instance_t* af_create(af_stream_t* s, char* name)
// Allocate space for the new filter and reset all pointers
af_instance_t* new=malloc(sizeof(af_instance_t));
if(!new){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory\n");
+ af_msg(AF_MSG_ERROR,"Could not allocate memory\n");
return NULL;
}
memset(new,0,sizeof(af_instance_t));
@@ -85,13 +88,13 @@ af_instance_t* af_create(af_stream_t* s, char* name)
non-reentrant */
if(new->info->flags & AF_FLAGS_NOT_REENTRANT){
if(af_get(s,name)){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"There can only be one instance of the filter '%s' in each stream\n",name);
+ af_msg(AF_MSG_ERROR,"There can only be one instance of the filter '%s' in each stream\n",name);
free(new);
return NULL;
}
}
- mp_msg(MSGT_AFILTER,MSGL_V,"Adding filter %s \n",name);
+ af_msg(AF_MSG_VERBOSE,"Adding filter %s \n",name);
// Initialize the new filter
if(AF_OK == new->info->open(new) &&
@@ -105,7 +108,7 @@ af_instance_t* af_create(af_stream_t* s, char* name)
}
free(new);
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't create or open audio filter '%s'\n",name);
+ af_msg(AF_MSG_ERROR,"Couldn't create or open audio filter '%s'\n",name);
return NULL;
}
@@ -206,56 +209,62 @@ int af_reinit(af_stream_t* s, af_instance_t* af)
case AF_OK:
break;
case AF_FALSE:{ // Configuration filter is needed
- af_instance_t* new = NULL;
- // Insert channels filter
- if((af->prev?af->prev->data->nch:s->input.nch) != in.nch){
- // Create channels filter
- if(NULL == (new = af_prepend(s,af,"channels")))
- return AF_ERROR;
- // Set number of output channels
- if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch)))
- return rv;
- // Initialize channels filter
- if(!new->prev)
- memcpy(&in,&(s->input),sizeof(af_data_t));
- else
- memcpy(&in,new->prev->data,sizeof(af_data_t));
- if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
- return rv;
- }
- // Insert format filter
- if(((af->prev?af->prev->data->format:s->input.format) != in.format) ||
- ((af->prev?af->prev->data->bps:s->input.bps) != in.bps)){
- // Create format filter
- if(NULL == (new = af_prepend(s,af,"format")))
+ // Do auto insertion only if force is not specified
+ if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){
+ af_instance_t* new = NULL;
+ // Insert channels filter
+ if((af->prev?af->prev->data->nch:s->input.nch) != in.nch){
+ // Create channels filter
+ if(NULL == (new = af_prepend(s,af,"channels")))
+ return AF_ERROR;
+ // Set number of output channels
+ if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch)))
+ return rv;
+ // Initialize channels filter
+ if(!new->prev)
+ memcpy(&in,&(s->input),sizeof(af_data_t));
+ else
+ memcpy(&in,new->prev->data,sizeof(af_data_t));
+ if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
+ return rv;
+ }
+ // Insert format filter
+ if(((af->prev?af->prev->data->format:s->input.format) != in.format) ||
+ ((af->prev?af->prev->data->bps:s->input.bps) != in.bps)){
+ // Create format filter
+ if(NULL == (new = af_prepend(s,af,"format")))
+ return AF_ERROR;
+ // Set output format
+ if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in)))
+ return rv;
+ // Initialize format filter
+ if(!new->prev)
+ memcpy(&in,&(s->input),sizeof(af_data_t));
+ else
+ memcpy(&in,new->prev->data,sizeof(af_data_t));
+ if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
+ return rv;
+ }
+ if(!new) // Should _never_ happen
return AF_ERROR;
- // Set output format
- if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in)))
- return rv;
- // Initialize format filter
- if(!new->prev)
- memcpy(&in,&(s->input),sizeof(af_data_t));
- else
- memcpy(&in,new->prev->data,sizeof(af_data_t));
- if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
- return rv;
+ af=new;
}
- if(!new) // Should _never_ happen
- return AF_ERROR;
- af=new;
break;
}
case AF_DETACH:{ // Filter is redundant and wants to be unloaded
- af_instance_t* aft=af->prev;
- af_remove(s,af);
- if(aft)
- af=aft;
- else
- af=s->first; // Restart configuration
+ // Do auto remove only if force is not specified
+ if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){
+ af_instance_t* aft=af->prev;
+ af_remove(s,af);
+ if(aft)
+ af=aft;
+ else
+ af=s->first; // Restart configuration
+ }
break;
}
default:
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv);
+ af_msg(AF_MSG_ERROR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv);
return AF_ERROR;
}
af=af->next;
@@ -289,13 +298,8 @@ int af_init(af_stream_t* s)
s->input.len = s->output.len = 0;
// Figure out how fast the machine is
- if(AF_INIT_AUTO == (AF_INIT_TYPE_MASK & s->cfg.force)){
-# if defined(HAVE_SSE) || defined(HAVE_3DNOWEX)
- s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_FAST;
-# else
- s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_SLOW;
-# endif
- }
+ if(AF_INIT_AUTO == (AF_INIT_TYPE_MASK & s->cfg.force))
+ s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_TYPE;
// Check if this is the first call
if(!s->first){
@@ -379,7 +383,7 @@ int af_init(af_stream_t* s)
(s->last->data->nch != s->output.nch) ||
(s->last->data->rate != s->output.rate)) {
// Something is stuffed audio out will not work
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n");
+ af_msg(AF_MSG_ERROR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n");
af_uninit(s);
return -1;
}
@@ -527,14 +531,14 @@ inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data)
{
// Calculate new length
register int len = af_lencalc(af->mul,data);
- mp_msg(MSGT_AFILTER,MSGL_V,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len);
+ af_msg(AF_MSG_VERBOSE,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len);
// If there is a buffer free it
if(af->data->audio)
free(af->data->audio);
// Create new buffer and check that it is OK
af->data->audio = malloc(len);
if(!af->data->audio){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory \n");
+ af_msg(AF_MSG_FATAL,"Could not allocate memory \n");
return AF_ERROR;
}
af->data->len=len;
diff --git a/libaf/af.h b/libaf/af.h
index 82a065ac95..33d0b271d4 100644
--- a/libaf/af.h
+++ b/libaf/af.h
@@ -1,4 +1,9 @@
+#include <stdio.h>
+
+#include "config.h"
#include "control.h"
+#include "af_format.h"
+#include "af_mp.h"
#ifndef __aop_h__
#define __aop_h__
@@ -23,7 +28,7 @@ typedef struct frac_s
int d; // Denominator
} frac_t;
-// Flags used for defining the behavour of an audio filter
+// Flags used for defining the behavior of an audio filter
#define AF_FLAGS_REENTRANT 0x00000000
#define AF_FLAGS_NOT_REENTRANT 0x00000001
@@ -56,16 +61,27 @@ typedef struct af_instance_s
}af_instance_t;
// Initialization flags
+extern int* af_cpu_speed;
+
#define AF_INIT_AUTO 0x00000000
#define AF_INIT_SLOW 0x00000001
#define AF_INIT_FAST 0x00000002
#define AF_INIT_FORCE 0x00000003
#define AF_INIT_TYPE_MASK 0x00000003
+// Default init type
+#ifndef AF_INIT_TYPE
+#if defined(HAVE_SSE) || defined(HAVE_3DNOW)
+#define AF_INIT_TYPE (af_cpu_speed?*af_cpu_speed:AF_INIT_FAST)
+#else
+#define AF_INIT_TYPE (af_cpu_speed?*af_cpu_speed:AF_INIT_SLOW)
+#endif
+#endif
+
// Configuration switches
typedef struct af_cfg_s{
int force; // Initialization type
- char** list; /* list of names of plugins that are added to filter
+ char** list; /* list of names of filters that are added to filter
list during first initialization of stream */
}af_cfg_t;
@@ -78,7 +94,7 @@ typedef struct af_stream_s
// Storage for input and output data formats
af_data_t input;
af_data_t output;
- // Cofiguration for this stream
+ // Configuration for this stream
af_cfg_t cfg;
}af_stream_t;
@@ -92,7 +108,7 @@ typedef struct af_stream_s
#define AF_FALSE 0
#define AF_UNKNOWN -1
#define AF_ERROR -2
-#define AF_NA -3
+#define AF_FATAL -3
@@ -100,12 +116,12 @@ typedef struct af_stream_s
// Export functions
*/
-/* Initialize the stream "s". This function creates a new fileterlist
- if nessesary according to the values set in input and output. Input
+/* Initialize the stream "s". This function creates a new filter list
+ if necessary according to the values set in input and output. Input
and output should contain the format of the current movie and the
formate of the preferred output respectively. The function is
- reentreant i.e. if called wit an already initialized stream the
- stream will be reinitialized. The return value is 0 if sucess and
+ reentrant i.e. if called wit an already initialized stream the
+ stream will be reinitialized. The return value is 0 if success and
-1 if failure */
int af_init(af_stream_t* s);
@@ -187,8 +203,37 @@ int af_lencalc(frac_t mul, af_data_t* data);
#define sign(a) (((a)>0)?(1):(-1))
#endif
-#ifndef lround
-#define lround(a,b) ((b)((a)>=0.0?(a)+0.5:(a)-0.5))
+#ifndef lrnd
+#define lrnd(a,b) ((b)((a)>=0.0?(a)+0.5:(a)-0.5))
#endif
+/* Error messages */
+
+typedef struct af_msg_cfg_s
+{
+ int level; /* Message level for debug and error messages max = 2
+ min = -2 default = 0 */
+ FILE* err; // Stream to print error messages to
+ FILE* msg; // Stream to print information messages to
+}af_msg_cfg_t;
+
+extern af_msg_cfg_t af_msg_cfg; // Message
+
+#define AF_MSG_FATAL -3 // Fatal error exit immediately
+#define AF_MSG_ERROR -2 // Error return gracefully
+#define AF_MSG_WARN -1 // Print warning but do not exit (can be suppressed)
+#define AF_MSG_INFO 0 // Important information
+#define AF_MSG_VERBOSE 1 // Print this if verbose is enabled
+#define AF_MSG_DEBUG0 2 // Print if very verbose
+#define AF_MSG_DEBUG1 3 // Print if very very verbose
+
+/* Macro for printing error messages */
+#ifndef af_msg
+#define af_msg(lev, args... ) \
+((lev<AF_MSG_WARN)?(fprintf(af_msg_cfg.err?af_msg_cfg.err:stderr, ## args )): \
+((lev<=af_msg_cfg.level)?(fprintf(af_msg_cfg.msg?af_msg_cfg.msg:stdout, ## args )):0))
#endif
+
+#endif /* __aop_h__ */
+
+
diff --git a/libaf/af_channels.c b/libaf/af_channels.c
index 2fc9837e37..f6cdba172c 100644
--- a/libaf/af_channels.c
+++ b/libaf/af_channels.c
@@ -8,9 +8,6 @@
#include <unistd.h>
#include <inttypes.h>
-#include "../config.h"
-#include "../mp_msg.h"
-
#include "af.h"
// Local function for copying data
@@ -70,7 +67,7 @@ void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, i
break;
}
default:
- mp_msg(MSGT_AFILTER,MSGL_ERR,"[channels] Unsupported number of bytes/sample: %i please report this error on the MPlayer mailing list. \n",bps);
+ af_msg(AF_MSG_ERROR,"[channels] Unsupported number of bytes/sample: %i please report this error on the MPlayer mailing list. \n",bps);
}
}
@@ -99,12 +96,12 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
// Sanity check
if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > 6){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"[channels] The number of output channels must be between 1 and 6. Current value is%i \n",((int*)arg)[0]);
+ af_msg(AF_MSG_ERROR,"[channels] The number of output channels must be between 1 and 6. Current value is%i \n",((int*)arg)[0]);
return AF_ERROR;
}
af->data->nch=((int*)arg)[0];
- mp_msg(MSGT_AFILTER,MSGL_V,"[channels] Changing number of channels to %i\n",af->data->nch);
+ af_msg(AF_MSG_VERBOSE,"[channels] Changing number of channels to %i\n",af->data->nch);
return AF_OK;
}
return AF_UNKNOWN;
diff --git a/libaf/af_delay.c b/libaf/af_delay.c
index 08c33499a8..f19dc1934b 100644
--- a/libaf/af_delay.c
+++ b/libaf/af_delay.c
@@ -7,9 +7,6 @@
#include <stdlib.h>
#include <string.h>
-#include "../config.h"
-#include "../mp_msg.h"
-
#include "af.h"
// Data for specific instances of this filter
@@ -43,7 +40,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
int lt = s->len; // Old len
if(*((float*)arg) > 30 || *((float*)arg) < 0){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Error setting delay length in af_delay. Delay must be between 0s and 30s\n");
+ af_msg(AF_MSG_ERROR,"Error setting delay length in af_delay. Delay must be between 0s and 30s\n");
s->len=0;
s->tlen=0.0;
af->delay=0.0;
@@ -55,8 +52,8 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
af->delay = s->tlen * 1000.0;
s->len = af->data->rate*af->data->bps*af->data->nch*(int)s->tlen;
s->buf = malloc(s->len);
- mp_msg(MSGT_AFILTER,MSGL_DBG2,"[delay] Delaying audio output by %0.2fs\n",s->tlen);
- mp_msg(MSGT_AFILTER,MSGL_DBG3,"[delay] Delaying audio output by %i bytes\n",s->len);
+ af_msg(AF_MSG_DEBUG0,"[delay] Delaying audio output by %0.2fs\n",s->tlen);
+ af_msg(AF_MSG_DEBUG1,"[delay] Delaying audio output by %i bytes\n",s->len);
// Out of memory error
if(!s->buf){
diff --git a/libaf/af_dummy.c b/libaf/af_dummy.c
index fa4b721028..ca9f56bc55 100644
--- a/libaf/af_dummy.c
+++ b/libaf/af_dummy.c
@@ -4,9 +4,6 @@
#include <stdlib.h>
#include <string.h>
-#include "../config.h"
-#include "../mp_msg.h"
-
#include "af.h"
// Initialization and runtime control
@@ -15,7 +12,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
switch(cmd){
case AF_CONTROL_REINIT:
memcpy(af->data,(af_data_t*)arg,sizeof(af_data_t));
- mp_msg(MSGT_AFILTER,MSGL_V,"[dummy] Was reinitialized, rate=%iHz, nch = %i, format = 0x%08X and bps = %i\n",af->data->rate,af->data->nch,af->data->format,af->data->bps);
+ af_msg(AF_MSG_VERBOSE,"[dummy] Was reinitialized, rate=%iHz, nch = %i, format = 0x%08X and bps = %i\n",af->data->rate,af->data->nch,af->data->format,af->data->bps);
return AF_OK;
}
return AF_UNKNOWN;
@@ -33,7 +30,7 @@ static af_data_t* play(struct af_instance_s* af, af_data_t* data)
{
// Do something necessary to get rid of annoying warning during compile
if(!af)
- printf("EEEK: Argument af == NULL in af_dummy.c play().");
+ af_msg(AF_MSG_ERROR,"EEEK: Argument af == NULL in af_dummy.c play().");
return data;
}
diff --git a/libaf/af_equalizer.c b/libaf/af_equalizer.c
index 8b6129df54..d33e84d47f 100644
--- a/libaf/af_equalizer.c
+++ b/libaf/af_equalizer.c
@@ -21,16 +21,12 @@
#include <inttypes.h>
#include <math.h>
-#include "../config.h"
-#include "../mp_msg.h"
-#include "../libao2/afmt.h"
-
#include "af.h"
#include "equalizer.h"
-#define NCH 6 // Max number of channels
-#define L 2 // Storage for filter taps
-#define KM 10 // Max number of bands
+#define NCH AF_NCH // Number of channels
+#define L 2 // Storage for filter taps
+#define KM 10 // Max number of bands
#define Q 1.2247449 /* Q value for band-pass filters 1.2247=(3/2)^(1/2)
gives 4dB suppression @ Fc*2 and Fc/2 */
@@ -80,13 +76,16 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
af->data->rate = ((af_data_t*)arg)->rate;
af->data->nch = ((af_data_t*)arg)->nch;
- af->data->format = AFMT_S16_LE;
+ af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
af->data->bps = 2;
// Calculate number of active filters
s->K=KM;
- while(F[s->K-1] > (float)af->data->rate/2.0)
+ while(F[s->K-1] > (float)af->data->rate/2.2)
s->K--;
+
+ if(s->K != KM)
+ af_msg(AF_MSG_INFO,"Limiting the number of filters to %i due to low sample rate.\n",s->K);
// Generate filter taps
for(k=0;k<s->K;k++)
@@ -95,7 +94,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
// Calculate how much this plugin adds to the overall time delay
af->delay += 2000.0/((float)af->data->rate);
- // Only AFMT_S16_LE is supported
+ // Only signed 16 bit little endian is supported
if(af->data->format != ((af_data_t*)arg)->format ||
af->data->bps != ((af_data_t*)arg)->bps)
return AF_FALSE;
diff --git a/libaf/af_format.c b/libaf/af_format.c
index d9ca5fd7e7..fb6e6d79f5 100644
--- a/libaf/af_format.c
+++ b/libaf/af_format.c
@@ -10,105 +10,184 @@
#include <inttypes.h>
#include <limits.h>
-#include "../config.h"
-#include "../mp_msg.h"
+#include "af.h"
-#include "../libao2/afmt.h"
-#include "af.h"
+/* Functions used by play to convert the input audio to the correct
+ format */
+
+/* The below includes retrives functions for converting to and from
+ ulaw and alaw */
+#include "af_format_ulaw.c"
+#include "af_format_alaw.c"
+
+// Switch endianess
+static void endian(void* in, void* out, int len, int bps);
+// From singed to unsigned
+static void si2us(void* in, void* out, int len, int bps);
+// From unsinged to signed
+static void us2si(void* in, void* out, int len, int bps);
+// Change the number of bits per sample
+static void change_bps(void* in, void* out, int len, int inbps, int outbps);
+// From float to int signed
+static void float2int(void* in, void* out, int len, int bps);
+// From signed int to float
+static void int2float(void* in, void* out, int len, int bps);
+
+// Convert from string to format
+static int str2fmt(char* str)
+{
+ int format=0;
+ // Scan for endianess
+ if(strstr(str,"be") || strstr(str,"BE"))
+ format |= AF_FORMAT_BE;
+ else if(strstr(str,"le") || strstr(str,"LE"))
+ format |= AF_FORMAT_LE;
+ else
+ format |= AF_FORMAT_NE;
+
+ // Scan for special formats
+ if(strstr(str,"mulaw") || strstr(str,"MULAW")){
+ format |= AF_FORMAT_MU_LAW; return format;
+ }
+ if(strstr(str,"alaw") || strstr(str,"ALAW")){
+ format |= AF_FORMAT_A_LAW; return format;
+ }
+ if(strstr(str,"ac3") || strstr(str,"AC3")){
+ format |= AF_FORMAT_AC3; return format;
+ }
+ if(strstr(str,"mpeg2") || strstr(str,"MPEG2")){
+ format |= AF_FORMAT_MPEG2; return format;
+ }
+ if(strstr(str,"imaadpcm") || strstr(str,"IMAADPCM")){
+ format |= AF_FORMAT_IMA_ADPCM; return format;
+ }
+
+ // Scan for int/float
+ if(strstr(str,"float") || strstr(str,"FLOAT")){
+ format |= AF_FORMAT_F; return format;
+ }
+ else
+ format |= AF_FORMAT_I;
+
+ // Scan for signed/unsigned
+ if(strstr(str,"unsigned") || strstr(str,"UNSIGNED"))
+ format |= AF_FORMAT_US;
+ else
+ format |= AF_FORMAT_SI;
+
+ return format;
+}
-// Number of bits
-#define B08 (0<<0)
-#define B16 (1<<0)
-#define B32 (2<<0)
-#define NBITS_MASK (3<<0)
-
-// Endianess
-#define BE (0<<2) // Big Endian
-#define LE (1<<2) // Little Endian
-#define END_MASK (1<<2)
-
-#if WORDS_BIGENDIAN // native endian of cpu
-#define NE BE
-#else
-#define NE LE
-#endif
-
-// Signed
-#define US (0<<3) // Un Signed
-#define SI (1<<3) // SIgned
-#define SIGN_MASK (1<<3)
-
-int decode(int format)
+/* Convert format to str input str is a buffer for the
+ converted string, size is the size of the buffer */
+static char* fmt2str(int format, char* str, size_t size)
{
- // Check input format
- switch(format){
- case(AFMT_U8):
- return LE|B08|US;
- case(AFMT_S8):
- return LE|B08|SI; break;
- case(AFMT_S16_LE):
- return LE|B16|SI; break;
- case(AFMT_S16_BE):
- return BE|B16|SI; break;
- case(AFMT_U16_LE):
- return LE|B16|US; break;
- case(AFMT_U16_BE):
- return BE|B16|US; break;
- case(AFMT_S32_LE):
- return LE|B32|SI; break;
- case(AFMT_S32_BE):
- return BE|B32|SI; break;
- case(AFMT_IMA_ADPCM):
- case(AFMT_MU_LAW):
- case(AFMT_A_LAW):
- case(AFMT_MPEG):
- case(AFMT_AC3):
- mp_msg(MSGT_AFILTER,MSGL_ERR,"[af_format] Input audio format not yet supported \n");
- return 0;
- default:
- //This can not happen ....
- mp_msg(MSGT_AFILTER,MSGL_ERR,"Unrecognized input audio format\n");
- return 0;
+ int i=0;
+ // Print endinaness
+ if(AF_FORMAT_LE == (format & AF_FORMAT_END_MASK))
+ i+=snprintf(str,size,"little endian ");
+ else
+ i+=snprintf(str,size,"big endian ");
+
+ if(format & AF_FORMAT_SPECIAL_MASK){
+ switch(format & AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_MU_LAW):
+ i+=snprintf(&str[i],size-i,"mu law "); break;
+ case(AF_FORMAT_A_LAW):
+ i+=snprintf(&str[i],size-i,"A law "); break;
+ case(AF_FORMAT_MPEG2):
+ i+=snprintf(&str[i],size-i,"MPEG 2 "); break;
+ case(AF_FORMAT_AC3):
+ i+=snprintf(&str[i],size-i,"AC3 "); break;
+ }
}
+ else{
+ // Point
+ if(AF_FORMAT_F == (format & AF_FORMAT_POINT_MASK))
+ i+=snprintf(&str[i],size,"float ");
+ else{
+ // Sign
+ if(AF_FORMAT_US == (format & AF_FORMAT_SIGN_MASK))
+ i+=snprintf(&str[i],size-i,"unsigned ");
+ else
+ i+=snprintf(&str[i],size-i,"signed ");
+ i+=snprintf(&str[i],size,"int ");
+ }
+ }
+ return str;
}
// Initialization and runtime control
static int control(struct af_instance_s* af, int cmd, void* arg)
{
switch(cmd){
- case AF_CONTROL_REINIT:
+ case AF_CONTROL_REINIT:{
+ char buf1[256];
+ char buf2[256];
// Make sure this filter isn't redundant
- if(af->data->format == ((af_data_t*)arg)->format && af->data->bps == ((af_data_t*)arg)->bps)
+ if(af->data->format == ((af_data_t*)arg)->format &&
+ af->data->bps == ((af_data_t*)arg)->bps)
return AF_DETACH;
+
+ // Sanity check for bytes per sample
+ if(((af_data_t*)arg)->bps != 4 && ((af_data_t*)arg)->bps != 2 &&
+ ((af_data_t*)arg)->bps != 1){
+ af_msg(AF_MSG_ERROR,"[format] The number of output bytes per sample must be 1, 2 or 4. Current value is %i \n",((af_data_t*)arg)->bps);
+ return AF_ERROR;
+ }
+
+ // Check for unsupported formats
+ switch(((af_data_t*)arg)->format & AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_MPEG2):
+ case(AF_FORMAT_AC3):
+ af_msg(AF_MSG_ERROR,"[format] Sample format not yet supported \n");
+ return AF_ERROR;
+ }
+
+ af_msg(AF_MSG_VERBOSE,"[format] Changing sample format from %ibit %sto %ibit %s \n",
+ ((af_data_t*)arg)->bps*8,fmt2str(((af_data_t*)arg)->format,buf1,256),
+ af->data->bps*8,fmt2str(af->data->format,buf2,256));
af->data->rate = ((af_data_t*)arg)->rate;
af->data->nch = ((af_data_t*)arg)->nch;
af->mul.n = af->data->bps;
af->mul.d = ((af_data_t*)arg)->bps;
return AF_OK;
+ }
case AF_CONTROL_COMMAND_LINE:{
- af_data_t d;
- sscanf((char*)arg,"%i:%i",&(d.format),&(d.bps));
+ af_data_t d={NULL,0,0,0,0,2};
+ char str[256];
+ sscanf((char*)arg,"%i:%s",&(d.bps),str);
+ // Convert string to format
+ d.format = str2fmt(str);
+ // Automatic correction of errors
+ switch(d.format & AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_A_LAW):
+ case(AF_FORMAT_MU_LAW):
+ d.bps=1; break;
+ case(AF_FORMAT_AC3):
+ d.bps=4; break; // I think
+ }
+ if(AF_FORMAT_F == (d.format & AF_FORMAT_POINT_MASK))
+ d.bps=4;
+
return af->control(af,AF_CONTROL_FORMAT,&d);
- }
+ }
case AF_CONTROL_FORMAT:
// Reinit must be called after this function has been called
- // Sanity check for sample format
- if(0 == ((int)af->setup=decode(((af_data_t*)arg)->format)))
- return AF_ERROR;
- af->data->format = ((af_data_t*)arg)->format;
-
- // Sanity check for bytes per sample
- if(((af_data_t*)arg)->bps != 4 && ((af_data_t*)arg)->bps != 2 && ((af_data_t*)arg)->bps != 1){
- mp_msg(MSGT_AFILTER,MSGL_ERR,"[format] The number of output bytes per sample must be 1, 2 or 4. Current value is%i \n",((af_data_t*)arg)->bps);
+ // Check for unsupported formats
+ switch(((af_data_t*)arg)->format & AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_MPEG2):
+ case(AF_FORMAT_AC3):
+ af_msg(AF_MSG_ERROR,"[format] Sample format not yet supported \n");
return AF_ERROR;
}
- af->data->bps=((af_data_t*)arg)->bps;
- mp_msg(MSGT_AFILTER,MSGL_V,"[format] Changing number sample format to 0x%08X and/or bytes per sample to %i \n",af->data->format,af->data->bps);
+ af->data->format = ((af_data_t*)arg)->format;
+ af->data->bps=((af_data_t*)arg)->bps;
return AF_OK;
}
return AF_UNKNOWN;
@@ -125,156 +204,86 @@ static void uninit(struct af_instance_s* af)
// Filter data through filter
static af_data_t* play(struct af_instance_s* af, af_data_t* data)
{
- af_data_t* l = af->data; // Local data
- void* la = NULL; // Local audio
- int lf = (int)af->setup; // Local format
- af_data_t* c = data; // Current working data
- void* ca = c->audio; // Current audio
- int cf = decode(c->format); // Current format
- register int i = 0; // Counter
- int len = c->len>>(cf&NBITS_MASK); // Loop end
+ af_data_t* l = af->data; // Local data
+ af_data_t* c = data; // Current working data
+ int len = c->len/c->bps; // Lenght in samples of current audio block
if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
return NULL;
- la = l->audio;
+ // Change to cpu native endian format
+ if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE)
+ endian(c->audio,c->audio,len,c->bps);
- // Change to cpu native endian
- if((cf&END_MASK)!=NE){
- switch(cf&NBITS_MASK){
- case(B16):{
- register uint16_t s;
- for(i=0;i<len;i++){
- s=((uint16_t*)ca)[i];
- ((uint16_t*)ca)[i]=(uint16_t)(((s&0x00FF)<<8) | (s&0xFF00)>>8);
- }
- }
+ // Conversion table
+ switch(c->format & ~AF_FORMAT_END_MASK){
+ case(AF_FORMAT_MU_LAW):
+ from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK);
+ if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK))
+ to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI);
+ if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US)
+ si2us(l->audio,l->audio,len,l->bps);
break;
- case(B32):{
- register uint32_t s;
- for(i=0;i<len;i++){
- s=((uint32_t*)ca)[i];
- ((uint32_t*)ca)[i]=(uint32_t)(((s&0x000000FF)<<24) | ((s&0x0000FF00)<<8) |
- ((s&0x00FF0000)>>8) | ((s&0xFF000000)>>24));
- }
- }
+ case(AF_FORMAT_A_LAW):
+ from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK);
+ if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK))
+ to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI);
+ if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US)
+ si2us(l->audio,l->audio,len,l->bps);
break;
- }
- }
-
- // Change signed/unsigned
- if((cf&SIGN_MASK) != (lf&SIGN_MASK)){
- switch((cf&NBITS_MASK)){
- case(B08):
- switch(cf&SIGN_MASK){
- case(US):
- for(i=0;i<len;i++)
- ((int8_t*)ca)[i]=(int8_t)(SCHAR_MIN+((int)((uint8_t*)ca)[i]));
- break;
- case(SI):
- for(i=0;i<len;i++)
- ((uint8_t*)ca)[i]=(uint8_t)(SCHAR_MAX+((int)((int8_t*)ca)[i]));
- break;
- }
+ case(AF_FORMAT_F):
+ float2int(c->audio, l->audio, len, l->bps);
+ switch(l->format&AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_MU_LAW):
+ to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK);
break;
- case(B16):
- switch(cf&SIGN_MASK){
- case(US):
- for(i=0;i<len;i++)
- ((int16_t*)ca)[i]=(int16_t)(SHRT_MIN+((int)((uint16_t*)ca)[i]));
- break;
- case(SI):
- for(i=0;i<len;i++)
- ((uint16_t*)ca)[i]=(uint16_t)(SHRT_MAX+((int)((int16_t*)ca)[i]));
- break;
- }
+ case(AF_FORMAT_A_LAW):
+ to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK);
break;
- case(B32):
- switch(cf&SIGN_MASK){
- case(US):
- for(i=0;i<len;i++)
- ((int32_t*)ca)[i]=(int32_t)(INT_MIN+((uint32_t*)ca)[i]);
- break;
- case(SI):
- for(i=0;i<len;i++)
- ((uint32_t*)ca)[i]=(uint32_t)(INT_MAX+((int32_t*)ca)[i]);
- break;
- }
+ }
+ if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US)
+ si2us(l->audio,l->audio,len,l->bps);
+ break;
+ default:
+ // Input must be int
+
+ // Change signed/unsigned
+ if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){
+ if((c->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US)
+ us2si(c->audio,c->audio,len,c->bps);
+ else
+ si2us(c->audio,c->audio,len,c->bps);
+ }
+ // Convert to special formats
+ switch(l->format&AF_FORMAT_SPECIAL_MASK){
+ case(AF_FORMAT_MU_LAW):
+ to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK);
break;