Search
lxdream.org :: lxdream/src/aica/audio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 657:c4143facbfcb
prev643:653b0a70f173
next697:479b8c213f61
author nkeynes
date Sun Jun 01 00:47:45 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change First cut of the Cocoa GUI implementation
file annotate diff log raw
nkeynes@66
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@66
     3
 * 
nkeynes@66
     4
 * Audio mixer core. Combines all the active streams into a single sound
nkeynes@66
     5
 * buffer for output. 
nkeynes@66
     6
 *
nkeynes@66
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@66
     8
 *
nkeynes@66
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@66
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@66
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@66
    12
 * (at your option) any later version.
nkeynes@66
    13
 *
nkeynes@66
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@66
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@66
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@66
    17
 * GNU General Public License for more details.
nkeynes@66
    18
 */
nkeynes@66
    19
nkeynes@66
    20
#include "aica/aica.h"
nkeynes@66
    21
#include "aica/audio.h"
nkeynes@66
    22
#include "glib/gmem.h"
nkeynes@66
    23
#include "dream.h"
nkeynes@66
    24
#include <assert.h>
nkeynes@66
    25
#include <string.h>
nkeynes@66
    26
nkeynes@531
    27
audio_driver_t audio_driver_list[] = { 
nkeynes@657
    28
#ifdef HAVE_PULSE
nkeynes@657
    29
                                       &audio_pulse_driver,
nkeynes@657
    30
#endif
nkeynes@531
    31
#ifdef HAVE_ESOUND
nkeynes@531
    32
				       &audio_esd_driver,
nkeynes@531
    33
#endif
bhaal22@643
    34
#ifdef HAVE_ALSA
bhaal22@643
    35
				       &audio_alsa_driver,
bhaal22@643
    36
#endif
nkeynes@531
    37
				       &audio_null_driver,
nkeynes@531
    38
				       NULL };
nkeynes@531
    39
nkeynes@66
    40
#define NUM_BUFFERS 3
nkeynes@434
    41
#define MS_PER_BUFFER 100
nkeynes@66
    42
nkeynes@66
    43
#define BUFFER_EMPTY   0
nkeynes@66
    44
#define BUFFER_WRITING 1
nkeynes@66
    45
#define BUFFER_FULL    2
nkeynes@66
    46
nkeynes@66
    47
struct audio_state {
nkeynes@66
    48
    audio_buffer_t output_buffers[NUM_BUFFERS];
nkeynes@66
    49
    int write_buffer;
nkeynes@66
    50
    int read_buffer;
nkeynes@66
    51
    uint32_t output_format;
nkeynes@66
    52
    uint32_t output_rate;
nkeynes@66
    53
    uint32_t output_sample_size;
nkeynes@465
    54
    struct audio_channel channels[AUDIO_CHANNEL_COUNT];
nkeynes@66
    55
} audio;
nkeynes@66
    56
nkeynes@66
    57
audio_driver_t audio_driver = NULL;
nkeynes@66
    58
nkeynes@66
    59
#define NEXT_BUFFER() ((audio.write_buffer == NUM_BUFFERS-1) ? 0 : audio.write_buffer+1)
nkeynes@66
    60
nkeynes@66
    61
extern char *arm_mem;
nkeynes@66
    62
nkeynes@66
    63
/**
nkeynes@465
    64
 * Preserve audio channel state only - don't bother saving the buffers
nkeynes@465
    65
 */
nkeynes@465
    66
void audio_save_state( FILE *f )
nkeynes@465
    67
{
nkeynes@465
    68
    fwrite( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
nkeynes@465
    69
}
nkeynes@465
    70
nkeynes@465
    71
int audio_load_state( FILE *f )
nkeynes@465
    72
{
nkeynes@465
    73
    int read = fread( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
nkeynes@465
    74
    return (read == AUDIO_CHANNEL_COUNT ? 0 : -1 );
nkeynes@465
    75
}
nkeynes@465
    76
nkeynes@531
    77
audio_driver_t get_audio_driver_by_name( const char *name )
nkeynes@531
    78
{
nkeynes@531
    79
    int i;
nkeynes@531
    80
    if( name == NULL ) {
nkeynes@531
    81
	return audio_driver_list[0];
nkeynes@531
    82
    }
nkeynes@531
    83
    for( i=0; audio_driver_list[i] != NULL; i++ ) {
nkeynes@531
    84
	if( strcasecmp( audio_driver_list[i]->name, name ) == 0 ) {
nkeynes@531
    85
	    return audio_driver_list[i];
nkeynes@531
    86
	}
nkeynes@531
    87
    }
nkeynes@531
    88
nkeynes@531
    89
    return NULL;
nkeynes@531
    90
}
nkeynes@531
    91
nkeynes@465
    92
/**
nkeynes@66
    93
 * Set the output driver, sample rate and format. Also initializes the 
nkeynes@66
    94
 * output buffers, flushing any current data and reallocating as 
nkeynes@66
    95
 * necessary.
nkeynes@66
    96
 */
nkeynes@111
    97
gboolean audio_set_driver( audio_driver_t driver, 
nkeynes@111
    98
			   uint32_t samplerate, int format )
nkeynes@66
    99
{
nkeynes@66
   100
    uint32_t bytes_per_sample = 1;
nkeynes@66
   101
    uint32_t samples_per_buffer;
nkeynes@66
   102
    int i;
nkeynes@66
   103
nkeynes@111
   104
    if( audio_driver == NULL || driver != NULL ) {
nkeynes@111
   105
	if( driver == NULL  )
nkeynes@111
   106
	    driver = &audio_null_driver;
nkeynes@111
   107
	if( driver != audio_driver ) {	
nkeynes@111
   108
	    if( !driver->set_output_format( samplerate, format ) )
nkeynes@111
   109
		return FALSE;
nkeynes@111
   110
	    audio_driver = driver;
nkeynes@111
   111
	}
nkeynes@111
   112
    }
nkeynes@111
   113
nkeynes@66
   114
    if( format & AUDIO_FMT_16BIT )
nkeynes@66
   115
	bytes_per_sample = 2;
nkeynes@66
   116
    if( format & AUDIO_FMT_STEREO )
nkeynes@66
   117
	bytes_per_sample <<= 1;
nkeynes@66
   118
    if( samplerate == audio.output_rate &&
nkeynes@66
   119
	bytes_per_sample == audio.output_sample_size )
nkeynes@431
   120
	return TRUE;
nkeynes@66
   121
    samples_per_buffer = (samplerate * MS_PER_BUFFER / 1000);
nkeynes@66
   122
    for( i=0; i<NUM_BUFFERS; i++ ) {
nkeynes@66
   123
	if( audio.output_buffers[i] != NULL )
nkeynes@66
   124
	    free(audio.output_buffers[i]);
nkeynes@66
   125
	audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
nkeynes@73
   126
	audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
nkeynes@66
   127
	audio.output_buffers[i]->posn = 0;
nkeynes@66
   128
	audio.output_buffers[i]->status = BUFFER_EMPTY;
nkeynes@66
   129
    }
nkeynes@66
   130
    audio.output_format = format;
nkeynes@66
   131
    audio.output_rate = samplerate;
nkeynes@66
   132
    audio.output_sample_size = bytes_per_sample;
nkeynes@66
   133
    audio.write_buffer = 0;
nkeynes@66
   134
    audio.read_buffer = 0;
nkeynes@66
   135
nkeynes@111
   136
    return TRUE;
nkeynes@66
   137
}
nkeynes@66
   138
nkeynes@66
   139
/**
nkeynes@66
   140
 * Mark the current write buffer as full and prepare the next buffer for
nkeynes@66
   141
 * writing. Returns the next buffer to write to.
nkeynes@66
   142
 * If all buffers are full, returns NULL.
nkeynes@66
   143
 */
nkeynes@66
   144
audio_buffer_t audio_next_write_buffer( )
nkeynes@66
   145
{
nkeynes@66
   146
    audio_buffer_t result = NULL;
nkeynes@66
   147
    audio_buffer_t current = audio.output_buffers[audio.write_buffer];
nkeynes@66
   148
    current->status = BUFFER_FULL;
nkeynes@66
   149
    if( audio.read_buffer == audio.write_buffer &&
nkeynes@66
   150
	audio_driver->process_buffer( current ) ) {
nkeynes@66
   151
	audio_next_read_buffer();
nkeynes@66
   152
    }
nkeynes@66
   153
    audio.write_buffer = NEXT_BUFFER();
nkeynes@66
   154
    result = audio.output_buffers[audio.write_buffer];
nkeynes@66
   155
    if( result->status == BUFFER_FULL )
nkeynes@66
   156
	return NULL;
nkeynes@66
   157
    else {
nkeynes@66
   158
	result->status = BUFFER_WRITING;
nkeynes@66
   159
	return result;
nkeynes@66
   160
    }
nkeynes@66
   161
}
nkeynes@66
   162
nkeynes@66
   163
/**
nkeynes@66
   164
 * Mark the current read buffer as empty and return the next buffer for
nkeynes@66
   165
 * reading. If there is no next buffer yet, returns NULL.
nkeynes@66
   166
 */
nkeynes@66
   167
audio_buffer_t audio_next_read_buffer( )
nkeynes@66
   168
{
nkeynes@66
   169
    audio_buffer_t current = audio.output_buffers[audio.read_buffer];
nkeynes@66
   170
    assert( current->status == BUFFER_FULL );
nkeynes@66
   171
    current->status = BUFFER_EMPTY;
nkeynes@66
   172
    current->posn = 0;
nkeynes@66
   173
    audio.read_buffer++;
nkeynes@66
   174
    if( audio.read_buffer == NUM_BUFFERS )
nkeynes@66
   175
	audio.read_buffer = 0;
nkeynes@66
   176
    
nkeynes@66
   177
    current = audio.output_buffers[audio.read_buffer];
nkeynes@66
   178
    if( current->status == BUFFER_FULL )
nkeynes@66
   179
	return current;
nkeynes@66
   180
    else return NULL;
nkeynes@66
   181
}
nkeynes@66
   182
nkeynes@66
   183
/*************************** ADPCM ***********************************/
nkeynes@66
   184
nkeynes@66
   185
/**
nkeynes@66
   186
 * The following section borrows heavily from ffmpeg, which is
nkeynes@66
   187
 * copyright (c) 2001-2003 by the fine folks at the ffmpeg project,
nkeynes@66
   188
 * distributed under the GPL version 2 or later.
nkeynes@66
   189
 */
nkeynes@66
   190
nkeynes@66
   191
#define CLAMP_TO_SHORT(value) \
nkeynes@66
   192
if (value > 32767) \
nkeynes@66
   193
    value = 32767; \
nkeynes@66
   194
else if (value < -32768) \
nkeynes@66
   195
    value = -32768; \
nkeynes@66
   196
nkeynes@66
   197
static const int yamaha_indexscale[] = {
nkeynes@66
   198
    230, 230, 230, 230, 307, 409, 512, 614,
nkeynes@66
   199
    230, 230, 230, 230, 307, 409, 512, 614
nkeynes@66
   200
};
nkeynes@66
   201
nkeynes@66
   202
static const int yamaha_difflookup[] = {
nkeynes@66
   203
    1, 3, 5, 7, 9, 11, 13, 15,
nkeynes@66
   204
    -1, -3, -5, -7, -9, -11, -13, -15
nkeynes@66
   205
};
nkeynes@66
   206
nkeynes@66
   207
static inline short adpcm_yamaha_decode_nibble( audio_channel_t c, 
nkeynes@66
   208
						unsigned char nibble )
nkeynes@66
   209
{
nkeynes@66
   210
    if( c->adpcm_step == 0 ) {
nkeynes@66
   211
        c->adpcm_predict = 0;
nkeynes@66
   212
        c->adpcm_step = 127;
nkeynes@66
   213
    }
nkeynes@66
   214
nkeynes@66
   215
    c->adpcm_predict += (c->adpcm_step * yamaha_difflookup[nibble]) >> 3;
nkeynes@66
   216
    CLAMP_TO_SHORT(c->adpcm_predict);
nkeynes@66
   217
    c->adpcm_step = (c->adpcm_step * yamaha_indexscale[nibble]) >> 8;
nkeynes@66
   218
    c->adpcm_step = CLAMP(c->adpcm_step, 127, 24567);
nkeynes@66
   219
    return c->adpcm_predict;
nkeynes@66
   220
}
nkeynes@66
   221
nkeynes@66
   222
/*************************** Sample mixer *****************************/
nkeynes@66
   223
nkeynes@66
   224
/**
nkeynes@66
   225
 * Mix a single output sample.
nkeynes@66
   226
 */
nkeynes@73
   227
void audio_mix_samples( int num_samples )
nkeynes@66
   228
{
nkeynes@66
   229
    int i, j;
nkeynes@73
   230
    int32_t result_buf[num_samples][2];
nkeynes@73
   231
nkeynes@73
   232
    memset( &result_buf, 0, sizeof(result_buf) );
nkeynes@66
   233
nkeynes@465
   234
    for( i=0; i < AUDIO_CHANNEL_COUNT; i++ ) {
nkeynes@66
   235
	audio_channel_t channel = &audio.channels[i];
nkeynes@66
   236
	if( channel->active ) {
nkeynes@66
   237
	    int32_t sample;
nkeynes@82
   238
	    int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
nkeynes@82
   239
	    int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
nkeynes@66
   240
	    switch( channel->sample_format ) {
nkeynes@66
   241
	    case AUDIO_FMT_16BIT:
nkeynes@73
   242
		for( j=0; j<num_samples; j++ ) {
nkeynes@434
   243
		    sample = ((int16_t *)(arm_mem + channel->start))[channel->posn];
nkeynes@82
   244
		    result_buf[j][0] += sample * vol_left;
nkeynes@82
   245
		    result_buf[j][1] += sample * vol_right;
nkeynes@73
   246
		    
nkeynes@73
   247
		    channel->posn_left += channel->sample_rate;
nkeynes@73
   248
		    while( channel->posn_left > audio.output_rate ) {
nkeynes@73
   249
			channel->posn_left -= audio.output_rate;
nkeynes@73
   250
			channel->posn++;
nkeynes@73
   251
			
nkeynes@73
   252
			if( channel->posn == channel->end ) {
nkeynes@463
   253
			    if( channel->loop ) {
nkeynes@73
   254
				channel->posn = channel->loop_start;
nkeynes@463
   255
				channel->loop = LOOP_LOOPED;
nkeynes@463
   256
			    } else {
nkeynes@73
   257
				audio_stop_channel(i);
nkeynes@73
   258
				j = num_samples;
nkeynes@73
   259
				break;
nkeynes@73
   260
			    }
nkeynes@73
   261
			}
nkeynes@73
   262
		    }
nkeynes@73
   263
		}
nkeynes@66
   264
		break;
nkeynes@66
   265
	    case AUDIO_FMT_8BIT:
nkeynes@73
   266
		for( j=0; j<num_samples; j++ ) {
nkeynes@434
   267
		    sample = ((int8_t *)(arm_mem + channel->start))[channel->posn] << 8;
nkeynes@82
   268
		    result_buf[j][0] += sample * vol_left;
nkeynes@82
   269
		    result_buf[j][1] += sample * vol_right;
nkeynes@73
   270
		    
nkeynes@73
   271
		    channel->posn_left += channel->sample_rate;
nkeynes@73
   272
		    while( channel->posn_left > audio.output_rate ) {
nkeynes@73
   273
			channel->posn_left -= audio.output_rate;
nkeynes@73
   274
			channel->posn++;
nkeynes@73
   275
			
nkeynes@73
   276
			if( channel->posn == channel->end ) {
nkeynes@463
   277
			    if( channel->loop ) {
nkeynes@73
   278
				channel->posn = channel->loop_start;
nkeynes@463
   279
				channel->loop = LOOP_LOOPED;
nkeynes@463
   280
			    } else {
nkeynes@73
   281
				audio_stop_channel(i);
nkeynes@73
   282
				j = num_samples;
nkeynes@73
   283
				break;
nkeynes@73
   284
			    }
nkeynes@73
   285
			}
nkeynes@73
   286
		    }
nkeynes@73
   287
		}
nkeynes@66
   288
		break;
nkeynes@66
   289
	    case AUDIO_FMT_ADPCM:
nkeynes@73
   290
		for( j=0; j<num_samples; j++ ) {
nkeynes@73
   291
		    sample = (int16_t)channel->adpcm_predict;
nkeynes@82
   292
		    result_buf[j][0] += sample * vol_left;
nkeynes@82
   293
		    result_buf[j][1] += sample * vol_right;
nkeynes@73
   294
		    channel->posn_left += channel->sample_rate;
nkeynes@73
   295
		    while( channel->posn_left > audio.output_rate ) {
nkeynes@73
   296
			channel->posn_left -= audio.output_rate;
nkeynes@434
   297
			channel->posn++;
nkeynes@434
   298
			if( channel->posn == channel->end ) {
nkeynes@434
   299
			    if( channel->loop ) {
nkeynes@434
   300
				channel->posn = channel->loop_start;
nkeynes@463
   301
				channel->loop = LOOP_LOOPED;
nkeynes@434
   302
				channel->adpcm_predict = 0;
nkeynes@434
   303
				channel->adpcm_step = 0;
nkeynes@434
   304
			    } else {
nkeynes@434
   305
				audio_stop_channel(i);
nkeynes@434
   306
				j = num_samples;
nkeynes@73
   307
				break;
nkeynes@73
   308
			    }
nkeynes@434
   309
			}
nkeynes@434
   310
			uint8_t data = ((uint8_t *)(arm_mem + channel->start))[channel->posn>>1];
nkeynes@434
   311
			if( channel->posn&1 ) {
nkeynes@434
   312
			    adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
nkeynes@434
   313
			} else {
nkeynes@73
   314
			    adpcm_yamaha_decode_nibble( channel, data & 0x0F );
nkeynes@73
   315
			}
nkeynes@73
   316
		    }
nkeynes@73
   317
		}
nkeynes@73
   318
		break;
nkeynes@66
   319
	    default:
nkeynes@73
   320
		break;
nkeynes@66
   321
	    }
nkeynes@66
   322
	}
nkeynes@66
   323
    }
nkeynes@73
   324
	    
nkeynes@66
   325
    /* Down-render to the final output format */
nkeynes@73
   326
    
nkeynes@66
   327
    if( audio.output_format & AUDIO_FMT_16BIT ) {
nkeynes@73
   328
	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
nkeynes@73
   329
	uint16_t *data = (uint16_t *)&buf->data[buf->posn];
nkeynes@73
   330
	for( j=0; j < num_samples; j++ ) {
nkeynes@82
   331
	    *data++ = (int16_t)(result_buf[j][0] >> 6);
nkeynes@82
   332
	    *data++ = (int16_t)(result_buf[j][1] >> 6);	
nkeynes@73
   333
	    buf->posn += 4;
nkeynes@73
   334
	    if( buf->posn == buf->length ) {
nkeynes@73
   335
		audio_next_write_buffer();
nkeynes@73
   336
		buf = audio.output_buffers[audio.write_buffer];
nkeynes@73
   337
		data = (uint16_t *)&buf->data[0];
nkeynes@73
   338
	    }
nkeynes@73
   339
	}
nkeynes@66
   340
    } else {
nkeynes@73
   341
	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
nkeynes@73
   342
	uint8_t *data = (uint8_t *)&buf->data[buf->posn];
nkeynes@73
   343
	for( j=0; j < num_samples; j++ ) {
nkeynes@73
   344
	    *data++ = (uint8_t)(result_buf[j][0] >> 16);
nkeynes@73
   345
	    *data++ = (uint8_t)(result_buf[j][1] >> 16);	
nkeynes@73
   346
	    buf->posn += 2;
nkeynes@73
   347
	    if( buf->posn == buf->length ) {
nkeynes@73
   348
		audio_next_write_buffer();
nkeynes@73
   349
		buf = audio.output_buffers[audio.write_buffer];
nkeynes@73
   350
		data = (uint8_t *)&buf->data[0];
nkeynes@73
   351
	    }
nkeynes@73
   352
	}
nkeynes@66
   353
    }
nkeynes@66
   354
}
nkeynes@66
   355
nkeynes@66
   356
/********************** Internal AICA calls ***************************/
nkeynes@66
   357
nkeynes@66
   358
audio_channel_t audio_get_channel( int channel ) 
nkeynes@66
   359
{
nkeynes@66
   360
    return &audio.channels[channel];
nkeynes@66
   361
}
nkeynes@66
   362
nkeynes@434
   363
void audio_start_stop_channel( int channel, gboolean start )
nkeynes@434
   364
{
nkeynes@434
   365
    if( audio.channels[channel].active ) {
nkeynes@434
   366
	if( !start ) {
nkeynes@434
   367
	    audio_stop_channel(channel);
nkeynes@434
   368
	}
nkeynes@434
   369
    } else if( start ) {
nkeynes@434
   370
	audio_start_channel(channel);
nkeynes@434
   371
    }
nkeynes@434
   372
}
nkeynes@434
   373
nkeynes@66
   374
void audio_stop_channel( int channel ) 
nkeynes@66
   375
{
nkeynes@66
   376
    audio.channels[channel].active = FALSE;
nkeynes@66
   377
}
nkeynes@66
   378
nkeynes@66
   379
nkeynes@66
   380
void audio_start_channel( int channel )
nkeynes@66
   381
{
nkeynes@66
   382
    audio.channels[channel].posn = 0;
nkeynes@66
   383
    audio.channels[channel].posn_left = 0;
nkeynes@66
   384
    audio.channels[channel].active = TRUE;
nkeynes@434
   385
    if( audio.channels[channel].sample_format == AUDIO_FMT_ADPCM ) {
nkeynes@434
   386
	audio.channels[channel].adpcm_step = 0;
nkeynes@434
   387
	audio.channels[channel].adpcm_predict = 0;
nkeynes@434
   388
	uint8_t data = ((uint8_t *)(arm_mem + audio.channels[channel].start))[0];
nkeynes@434
   389
	adpcm_yamaha_decode_nibble( &audio.channels[channel], data & 0x0F );
nkeynes@434
   390
    }
nkeynes@66
   391
}
.