[xiph-commits] r16803 - in trunk/ao: include/ao src
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Mon Jan 25 05:01:13 PST 2010
Author: xiphmont
Date: 2010-01-25 05:01:13 -0800 (Mon, 25 Jan 2010)
New Revision: 16803
Modified:
trunk/ao/include/ao/ao_private.h
trunk/ao/src/audio_out.c
Log:
Channel mappings now active and working;
only the alsa09 driver has it actually enabled (for now).
Modified: trunk/ao/include/ao/ao_private.h
===================================================================
--- trunk/ao/include/ao/ao_private.h 2010-01-25 07:17:41 UTC (rev 16802)
+++ trunk/ao/include/ao/ao_private.h 2010-01-25 13:01:13 UTC (rev 16803)
@@ -68,13 +68,19 @@
int driver_id;
ao_functions *funcs;
FILE *file; /* File for output if this is a file driver */
+
+ /* input not necessarily == output. Right now, byte order and
+ channel mappings may be altered. */
+
int client_byte_format;
int machine_byte_format;
int driver_byte_format;
char *swap_buffer;
int swap_buffer_size; /* Bytes allocated to swap_buffer */
+ int input_channels;
int output_channels;
+ int bytewidth;
char *output_matrix;
int *permute_channels;
void *internal; /* Pointer to driver-specific data */
Modified: trunk/ao/src/audio_out.c
===================================================================
--- trunk/ao/src/audio_out.c 2010-01-25 07:17:41 UTC (rev 16802)
+++ trunk/ao/src/audio_out.c 2010-01-25 13:01:13 UTC (rev 16803)
@@ -406,7 +406,7 @@
{
ao_device *device;
- device = malloc(sizeof(ao_device));
+ device = calloc(1,sizeof(ao_device));
if (device != NULL) {
device->type = driver->functions->driver_info()->type;
@@ -448,6 +448,125 @@
}
+static void _buffer_zero(char *target,int och,int bytewidth,int ochannels,int bytes){
+ int i = och*bytewidth;
+ int stride = bytewidth*ochannels;
+ switch(bytewidth){
+ case 1:
+ while(i<bytes){
+ ((unsigned char *)target)[i] = 128; /* 8 bit PCM is unsigned in libao */
+ i+=stride;
+ }
+ break;
+ case 2:
+ while(i<bytes){
+ target[i] = 0;
+ target[i+1] = 0;
+ i+=stride;
+ }
+ break;
+ case 3:
+ while(i<bytes){
+ target[i] = 0;
+ target[i+1] = 0;
+ target[i+2] = 0;
+ i+=stride;
+ }
+ break;
+ case 4:
+ while(i<bytes){
+ target[i] = 0;
+ target[i+1] = 0;
+ target[i+2] = 0;
+ target[i+3] = 0;
+ i+=stride;
+ }
+ break;
+ }
+}
+
+static void _buffer_permute_swap(char *target,int och,int bytewidth,int ochannels,int bytes,
+ char *source,int ich, int ichannels){
+ int o = och*bytewidth;
+ int i = ich*bytewidth;
+ int ostride = bytewidth*ochannels;
+ int istride = bytewidth*ichannels;
+ switch(bytewidth){
+ case 2:
+ while(o<bytes){
+ target[o] = source[i+1];
+ target[o+1] = source[i];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ case 3:
+ while(o<bytes){
+ target[o] = source[i+2];
+ target[o+1] = source[i+1];
+ target[o+2] = source[i];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ case 4:
+ while(o<bytes){
+ target[o] = source[i+3];
+ target[o+1] = source[i+2];
+ target[o+2] = source[i+1];
+ target[o+3] = source[i];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ }
+}
+
+static void _buffer_permute(char *target,int och,int bytewidth,int ochannels,int bytes,
+ char *source,int ich, int ichannels){
+ int o = och*bytewidth;
+ int i = ich*bytewidth;
+ int ostride = bytewidth*ochannels;
+ int istride = bytewidth*ichannels;
+ switch(bytewidth){
+ case 1:
+ while(o<bytes){
+ target[o] = source[i];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ case 2:
+ while(o<bytes){
+ target[o] = source[i];
+ target[o+1] = source[i+1];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ case 3:
+ while(o<bytes){
+ target[o] = source[i];
+ target[o+1] = source[i+1];
+ target[o+2] = source[i+2];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ case 4:
+ while(o<bytes){
+ target[o] = source[i];
+ target[o+1] = source[i+1];
+ target[o+2] = source[i+2];
+ target[o+3] = source[i+3];
+ o+=ostride;
+ i+=istride;
+ }
+ break;
+ }
+}
+
+
/* Swap and copy the byte order of samples from the source buffer to
the target buffer. */
static void _swap_samples(char *target_buffer, char* source_buffer,
@@ -461,9 +580,9 @@
}
}
-/* the channel locations we know right now. code below assumes M is in slot 0 */
+/* the channel locations we know right now. code below assumes U is in slot 0, M in slot 1 */
static char *mnemonics[]={
- "M","L","C","R","CL","CR","SL","SR","BL","BC","BR","LFE","U",
+ "U","M","L","C","R","CL","CR","SL","SR","BL","BC","BR","LFE",
"A1","A2","A3","A4","A5","A6","A7","A8","A9",NULL
};
@@ -619,6 +738,10 @@
fprintf(stderr,"Input channel matrix invalid; ignoring.\n");
}
+ /* set up any other housekeeping */
+ device->input_channels = sformat.channels;
+ device->bytewidth = (sformat.bits+7)>>3;
+
/* Open the device */
result = funcs->open(device, &sformat);
if (!result) {
@@ -650,7 +773,7 @@
int m=0,mm;
char *h=op;
- if(op){
+ if(*op){
/* find mnemonic offset of output channel */
while(*h && *h!=',')h++;
while(mnemonics[m]){
@@ -663,14 +786,14 @@
/* find match in input if any */
device->permute_channels[count] = _find_channel(m,sformat.matrix);
if(device->permute_channels[count] == -1 && sformat.channels == 1){
- device->permute_channels[count] = _find_channel(0,sformat.matrix);
+ device->permute_channels[count] = _find_channel(1,sformat.matrix);
mm=0;
}
}else
device->permute_channels[count] = -1;
/* display resulting mapping for now */
- if(device->verbose>0)
+ if(device->verbose>0){
if(device->permute_channels[count]>=0){
fprintf(stderr,"Output %d (%s)\t <- input %d (%s)\n",
count,mnemonics[m],device->permute_channels[count],
@@ -679,43 +802,59 @@
fprintf(stderr,"Output %d (%s)\t <- none\n",
count,mnemonics[m]);
}
+ }
count++;
- if(!h)
- op=NULL;
- else
- op=h+1;
+ op=h;
+ if(*h)op++;
}
+ if(device->verbose>0)
+ fprintf(stderr,"\n");
+
}
}
+ /* if there's no actual permutation to do, release the permutation vector */
+ if(device->permute_channels && device->output_channels == device->input_channels){
+ int i;
+ for(i=0;i<device->output_channels;i++)
+ if(device->permute_channels[i]!=i)break;
+ if(i==device->output_channels){
+ free(device->permute_channels);
+ device->permute_channels=NULL;
+ }
+ }
+
/* Resolve actual driver byte format */
device->driver_byte_format =
_real_byte_format(device->driver_byte_format);
- /* Only create swap buffer for 16 bit samples if needed */
- if (format->bits == 16 &&
- device->client_byte_format != device->driver_byte_format) {
+ /* Only create swap buffer if needed */
+ if (device->bytewidth>1 &&
+ device->client_byte_format != device->driver_byte_format &&
+ device->verbose>0)
+ fprintf(stderr,
+ "n\n\n\n-------------------------\n"
+ "machine endianness: %d\n"
+ "device->client_byte_format:%d\n"
+ "device->driver_byte_format:%d\n"
+ "--------------------------\n",
+ ao_is_big_endian(),device->client_byte_format,device->driver_byte_format);
- if(device->verbose>0)
- fprintf(stderr,
- "n\n\n\n-------------------------\n"
- "big : %d\n"
- "device->client_byte_format:%d\n"
- "device->driver_byte_format:%d\n"
- "--------------------------\n",
- ao_is_big_endian(),device->client_byte_format,device->driver_byte_format);
+ if ( (device->bytewidth>1 &&
+ device->client_byte_format != device->driver_byte_format) ||
+ device->permute_channels){
- result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE);
+ result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE);
- if (!result) {
+ if (!result) {
- if(sformat.matrix)free(sformat.matrix);
- device->funcs->close(device);
- device->funcs->device_clear(device);
- free(device);
- errno = AO_EFAIL;
- return NULL; /* Couldn't alloc swap buffer */
- }
+ if(sformat.matrix)free(sformat.matrix);
+ device->funcs->close(device);
+ device->funcs->device_clear(device);
+ free(device);
+ errno = AO_EFAIL;
+ return NULL; /* Couldn't alloc swap buffer */
+ }
}
/* If we made it this far, everything is OK. */
@@ -866,17 +1005,31 @@
if (device == NULL)
return 0;
-#if 1
if (device->swap_buffer != NULL) {
- if (_realloc_swap_buffer(device, num_bytes)) {
- _swap_samples(device->swap_buffer,
- output_samples, num_bytes);
- playback_buffer = device->swap_buffer;
- } else
- return 0; /* Could not expand swap buffer */
+ int out_bytes = num_bytes*device->output_channels/device->input_channels;
+ if (_realloc_swap_buffer(device, out_bytes)) {
+ int i;
+ int swap = (device->bytewidth>1 &&
+ device->client_byte_format != device->driver_byte_format);
+ for(i=0;i<device->output_channels;i++){
+ int ic = device->permute_channels[i];
+ if(ic==-1){
+ _buffer_zero(device->swap_buffer,i,device->bytewidth,device->output_channels,
+ out_bytes);
+ }else if(swap){
+ _buffer_permute_swap(device->swap_buffer,i,device->bytewidth,device->output_channels,
+ out_bytes, output_samples, ic, device->input_channels);
+ }else{
+ _buffer_permute(device->swap_buffer,i,device->bytewidth,device->output_channels,
+ out_bytes, output_samples, ic, device->input_channels);
+ }
+ }
+ playback_buffer = device->swap_buffer;
+ num_bytes = out_bytes;
+ } else
+ return 0; /* Could not expand swap buffer */
} else
-#endif
- playback_buffer = output_samples;
+ playback_buffer = output_samples;
return device->funcs->play(device, playback_buffer, num_bytes);
}
More information about the commits
mailing list