Search
lxdream.org :: lxdream/src/aica/audio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 1089:a3984d242909
prev1024:c67f2d61ab97
next1296:30ecee61f811
author nkeynes
date Fri Mar 02 23:49:10 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Android WIP:
* Rename gui_jni.c to gui_android.c - now quite android specific.
* Implement generic EGL driver with very minimal Java wrapper
* Run emulation in separate thread, and implement simple queue for
inter-thread communication.
* Add menu/action-bar items for start + reset
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@700
    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@1024
    27
#define MAX_AUDIO_DRIVERS 16
nkeynes@697
    28
extern struct audio_driver audio_null_driver;
nkeynes@697
    29
extern struct audio_driver audio_osx_driver;
nkeynes@697
    30
extern struct audio_driver audio_pulse_driver;
nkeynes@697
    31
extern struct audio_driver audio_esd_driver;
nkeynes@697
    32
extern struct audio_driver audio_alsa_driver;
nkeynes@989
    33
extern struct audio_driver audio_sdl_driver;
nkeynes@697
    34
nkeynes@1024
    35
static int audio_driver_count = 0;
nkeynes@1024
    36
static audio_driver_t audio_driver_list[MAX_AUDIO_DRIVERS] = {};
nkeynes@531
    37
nkeynes@66
    38
#define NUM_BUFFERS 3
nkeynes@700
    39
#define MS_PER_BUFFER 100
nkeynes@66
    40
nkeynes@66
    41
#define BUFFER_EMPTY   0
nkeynes@66
    42
#define BUFFER_WRITING 1
nkeynes@66
    43
#define BUFFER_FULL    2
nkeynes@66
    44
nkeynes@66
    45
struct audio_state {
nkeynes@66
    46
    audio_buffer_t output_buffers[NUM_BUFFERS];
nkeynes@66
    47
    int write_buffer;
nkeynes@66
    48
    int read_buffer;
nkeynes@66
    49
    uint32_t output_format;
nkeynes@66
    50
    uint32_t output_rate;
nkeynes@66
    51
    uint32_t output_sample_size;
nkeynes@465
    52
    struct audio_channel channels[AUDIO_CHANNEL_COUNT];
nkeynes@66
    53
} audio;
nkeynes@66
    54
nkeynes@66
    55
audio_driver_t audio_driver = NULL;
nkeynes@66
    56
nkeynes@66
    57
#define NEXT_BUFFER() ((audio.write_buffer == NUM_BUFFERS-1) ? 0 : audio.write_buffer+1)
nkeynes@66
    58
nkeynes@66
    59
/**
nkeynes@465
    60
 * Preserve audio channel state only - don't bother saving the buffers
nkeynes@465
    61
 */
nkeynes@465
    62
void audio_save_state( FILE *f )
nkeynes@465
    63
{
nkeynes@465
    64
    fwrite( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
nkeynes@465
    65
}
nkeynes@465
    66
nkeynes@465
    67
int audio_load_state( FILE *f )
nkeynes@465
    68
{
nkeynes@465
    69
    int read = fread( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
nkeynes@465
    70
    return (read == AUDIO_CHANNEL_COUNT ? 0 : -1 );
nkeynes@465
    71
}
nkeynes@465
    72
nkeynes@1024
    73
static int audio_driver_priority_compare(const void *a, const void *b)
nkeynes@1024
    74
{
nkeynes@1024
    75
    audio_driver_t ada = *(audio_driver_t *)a;
nkeynes@1024
    76
    audio_driver_t adb = *(audio_driver_t *)b;
nkeynes@1024
    77
    return ada->priority - adb->priority;
nkeynes@1024
    78
}
nkeynes@1024
    79
nkeynes@1024
    80
static int audio_driver_name_compare(const void *a, const void *b)
nkeynes@1024
    81
{
nkeynes@1024
    82
    audio_driver_t ada = *(audio_driver_t *)a;
nkeynes@1024
    83
    audio_driver_t adb = *(audio_driver_t *)b;
nkeynes@1024
    84
    return strcasecmp( ada->name, adb->name );
nkeynes@1024
    85
}
nkeynes@1024
    86
nkeynes@1024
    87
nkeynes@1024
    88
nkeynes@1024
    89
gboolean audio_register_driver( audio_driver_t driver )
nkeynes@1024
    90
{
nkeynes@1024
    91
    if( audio_driver_count >= MAX_AUDIO_DRIVERS ) {
nkeynes@1024
    92
        return FALSE;
nkeynes@1024
    93
    }
nkeynes@1024
    94
    audio_driver_list[audio_driver_count++] = driver;
nkeynes@1024
    95
    qsort( audio_driver_list, audio_driver_count, sizeof( audio_driver_t ), audio_driver_priority_compare );
nkeynes@1024
    96
    return TRUE;
nkeynes@1024
    97
}
nkeynes@1024
    98
nkeynes@531
    99
audio_driver_t get_audio_driver_by_name( const char *name )
nkeynes@531
   100
{
nkeynes@531
   101
    int i;
nkeynes@531
   102
    if( name == NULL ) {
nkeynes@697
   103
        return audio_driver_list[0];
nkeynes@531
   104
    }
nkeynes@1024
   105
    for( i=0; i < audio_driver_count; i++ ) {
nkeynes@697
   106
        if( strcasecmp( audio_driver_list[i]->name, name ) == 0 ) {
nkeynes@697
   107
            return audio_driver_list[i];
nkeynes@697
   108
        }
nkeynes@531
   109
    }
nkeynes@531
   110
nkeynes@531
   111
    return NULL;
nkeynes@531
   112
}
nkeynes@531
   113
nkeynes@700
   114
void print_audio_drivers( FILE * out )
nkeynes@700
   115
{
nkeynes@700
   116
    int i;
nkeynes@1024
   117
    audio_driver_t temp_list[MAX_AUDIO_DRIVERS];
nkeynes@1024
   118
    memcpy( temp_list, audio_driver_list, audio_driver_count*sizeof(audio_driver_t) );
nkeynes@1024
   119
    qsort( temp_list, audio_driver_count, sizeof(audio_driver_t), audio_driver_name_compare );
nkeynes@700
   120
    fprintf( out, "Available audio drivers:\n" );
nkeynes@1024
   121
    for( i=0; i < audio_driver_count; i++ ) {
nkeynes@1024
   122
        fprintf( out, "  %-8s %s\n", temp_list[i]->name,
nkeynes@1024
   123
                gettext(temp_list[i]->description) );
nkeynes@700
   124
    }
nkeynes@700
   125
}
nkeynes@700
   126
nkeynes@697
   127
audio_driver_t audio_init_driver( const char *preferred_driver )
nkeynes@697
   128
{
nkeynes@697
   129
    audio_driver_t audio_driver = get_audio_driver_by_name(preferred_driver);
nkeynes@697
   130
    if( audio_driver == NULL ) {
nkeynes@697
   131
        ERROR( "Audio driver '%s' not found, aborting.", preferred_driver );
nkeynes@697
   132
        exit(2);
nkeynes@697
   133
    } else if( audio_set_driver( audio_driver ) == FALSE ) {
nkeynes@779
   134
        int i;
nkeynes@1024
   135
        for( i=0; i < audio_driver_count; i++ ) {
nkeynes@779
   136
            if( audio_driver_list[i] != audio_driver &&
nkeynes@779
   137
                audio_set_driver( audio_driver_list[i] ) ) {
nkeynes@779
   138
                ERROR( "Failed to initialize audio driver %s, falling back to %s", 
nkeynes@779
   139
                       audio_driver->name, audio_driver_list[i]->name );
nkeynes@779
   140
                return audio_driver_list[i];
nkeynes@779
   141
            }
nkeynes@779
   142
        }
nkeynes@779
   143
        ERROR( "Unable to intialize any audio driver, aborting." );
nkeynes@779
   144
        exit(2);
nkeynes@759
   145
    }
nkeynes@759
   146
    return audio_driver;
nkeynes@697
   147
}
nkeynes@697
   148
nkeynes@1024
   149
void audio_start_driver(void)
nkeynes@1024
   150
{
nkeynes@1024
   151
    if( audio_driver != NULL && audio_driver->start != NULL ) {
nkeynes@1024
   152
        audio_driver->start();
nkeynes@1024
   153
    }
nkeynes@1024
   154
}
nkeynes@1024
   155
nkeynes@1024
   156
void audio_stop_driver(void)
nkeynes@1024
   157
{
nkeynes@1024
   158
    if( audio_driver != NULL && audio_driver->stop != NULL ) {
nkeynes@1024
   159
        audio_driver->stop();
nkeynes@1024
   160
    }
nkeynes@1024
   161
}
nkeynes@1024
   162
nkeynes@465
   163
/**
nkeynes@66
   164
 * Set the output driver, sample rate and format. Also initializes the 
nkeynes@66
   165
 * output buffers, flushing any current data and reallocating as 
nkeynes@66
   166
 * necessary.
nkeynes@66
   167
 */
nkeynes@697
   168
gboolean audio_set_driver( audio_driver_t driver )
nkeynes@66
   169
{
nkeynes@66
   170
    uint32_t bytes_per_sample = 1;
nkeynes@66
   171
    uint32_t samples_per_buffer;
nkeynes@66
   172
    int i;
nkeynes@66
   173
nkeynes@111
   174
    if( audio_driver == NULL || driver != NULL ) {
nkeynes@697
   175
        if( driver == NULL  )
nkeynes@697
   176
            driver = &audio_null_driver;
nkeynes@697
   177
        if( driver != audio_driver ) {	
nkeynes@697
   178
            if( !driver->init() )
nkeynes@697
   179
                return FALSE;
nkeynes@697
   180
            audio_driver = driver;
nkeynes@697
   181
        }
nkeynes@111
   182
    }
nkeynes@111
   183
nkeynes@697
   184
    switch( driver->sample_format & AUDIO_FMT_SAMPLE_MASK ) {
nkeynes@697
   185
    case AUDIO_FMT_8BIT:
nkeynes@697
   186
        bytes_per_sample = 1;
nkeynes@697
   187
        break;
nkeynes@697
   188
    case AUDIO_FMT_16BIT:
nkeynes@697
   189
        bytes_per_sample = 2;
nkeynes@697
   190
        break;
nkeynes@697
   191
    case AUDIO_FMT_FLOAT:
nkeynes@697
   192
        bytes_per_sample = 4;
nkeynes@697
   193
        break;
nkeynes@697
   194
    }
nkeynes@697
   195
nkeynes@697
   196
    if( driver->sample_format & AUDIO_FMT_STEREO )
nkeynes@697
   197
        bytes_per_sample <<= 1;
nkeynes@697
   198
    if( driver->sample_rate == audio.output_rate &&
nkeynes@697
   199
            bytes_per_sample == audio.output_sample_size )
nkeynes@697
   200
        return TRUE;
nkeynes@697
   201
    samples_per_buffer = (driver->sample_rate * MS_PER_BUFFER / 1000);
nkeynes@66
   202
    for( i=0; i<NUM_BUFFERS; i++ ) {
nkeynes@697
   203
        if( audio.output_buffers[i] != NULL )
nkeynes@697
   204
            free(audio.output_buffers[i]);
nkeynes@697
   205
        audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
nkeynes@697
   206
        audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
nkeynes@697
   207
        audio.output_buffers[i]->posn = 0;
nkeynes@697
   208
        audio.output_buffers[i]->status = BUFFER_EMPTY;
nkeynes@66
   209
    }
nkeynes@697
   210
    audio.output_format = driver->sample_format;
nkeynes@697
   211
    audio.output_rate = driver->sample_rate;
nkeynes@66
   212
    audio.output_sample_size = bytes_per_sample;
nkeynes@66
   213
    audio.write_buffer = 0;
nkeynes@66
   214
    audio.read_buffer = 0;
nkeynes@66
   215
nkeynes@111
   216
    return TRUE;
nkeynes@66
   217
}
nkeynes@66
   218
nkeynes@66
   219
/**
nkeynes@66
   220
 * Mark the current write buffer as full and prepare the next buffer for
nkeynes@66
   221
 * writing. Returns the next buffer to write to.
nkeynes@66
   222
 * If all buffers are full, returns NULL.
nkeynes@66
   223
 */
nkeynes@66
   224
audio_buffer_t audio_next_write_buffer( )
nkeynes@66
   225
{
nkeynes@66
   226
    audio_buffer_t result = NULL;
nkeynes@66
   227
    audio_buffer_t current = audio.output_buffers[audio.write_buffer];
nkeynes@66
   228
    current->status = BUFFER_FULL;
nkeynes@66
   229
    if( audio.read_buffer == audio.write_buffer &&
nkeynes@697
   230
            audio_driver->process_buffer( current ) ) {
nkeynes@697
   231
        audio_next_read_buffer();
nkeynes@66
   232
    }
nkeynes@697
   233
    int next_buffer = NEXT_BUFFER();
nkeynes@697
   234
    result = audio.output_buffers[next_buffer];
nkeynes@66
   235
    if( result->status == BUFFER_FULL )
nkeynes@697
   236
        return NULL;
nkeynes@66
   237
    else {
nkeynes@697
   238
        audio.write_buffer = next_buffer;
nkeynes@697
   239
        result->status = BUFFER_WRITING;
nkeynes@697
   240
        return result;
nkeynes@66
   241
    }
nkeynes@66
   242
}
nkeynes@66
   243
nkeynes@66
   244
/**
nkeynes@66
   245
 * Mark the current read buffer as empty and return the next buffer for
nkeynes@66
   246
 * reading. If there is no next buffer yet, returns NULL.
nkeynes@66
   247
 */
nkeynes@66
   248
audio_buffer_t audio_next_read_buffer( )
nkeynes@66
   249
{
nkeynes@66
   250
    audio_buffer_t current = audio.output_buffers[audio.read_buffer];
nkeynes@697
   251
    if( current->status == BUFFER_FULL ) {
nkeynes@697
   252
        // Current read buffer has data, which we've just emptied
nkeynes@697
   253
        current->status = BUFFER_EMPTY;
nkeynes@697
   254
        current->posn = 0;
nkeynes@697
   255
        audio.read_buffer++;
nkeynes@697
   256
        if( audio.read_buffer == NUM_BUFFERS )
nkeynes@697
   257
            audio.read_buffer = 0;
nkeynes@697
   258
nkeynes@697
   259
        current = audio.output_buffers[audio.read_buffer];
nkeynes@697
   260
        if( current->status == BUFFER_FULL ) {
nkeynes@697
   261
            current->posn = 0;
nkeynes@697
   262
            return current;
nkeynes@697
   263
        }
nkeynes@697
   264
        else return NULL;
nkeynes@697
   265
    } else {
nkeynes@697
   266
        return NULL;
nkeynes@697
   267
    }
nkeynes@697
   268
nkeynes@66
   269
}
nkeynes@66
   270
nkeynes@66
   271
/*************************** ADPCM ***********************************/
nkeynes@66
   272
nkeynes@66
   273
/**
nkeynes@66
   274
 * The following section borrows heavily from ffmpeg, which is
nkeynes@66
   275
 * copyright (c) 2001-2003 by the fine folks at the ffmpeg project,
nkeynes@66
   276
 * distributed under the GPL version 2 or later.
nkeynes@66
   277
 */
nkeynes@66
   278
nkeynes@66
   279
#define CLAMP_TO_SHORT(value) \
nkeynes@736
   280
    if (value > 32767) \
nkeynes@66
   281
    value = 32767; \
nkeynes@736
   282
    else if (value < -32768) \
nkeynes@66
   283
    value = -32768; \
nkeynes@66
   284
nkeynes@66
   285
static const int yamaha_indexscale[] = {
nkeynes@736
   286
        230, 230, 230, 230, 307, 409, 512, 614,
nkeynes@736
   287
        230, 230, 230, 230, 307, 409, 512, 614
nkeynes@66
   288
};
nkeynes@66
   289
nkeynes@66
   290
static const int yamaha_difflookup[] = {
nkeynes@736
   291
        1, 3, 5, 7, 9, 11, 13, 15,
nkeynes@736
   292
        -1, -3, -5, -7, -9, -11, -13, -15
nkeynes@66
   293
};
nkeynes@66
   294
nkeynes@66
   295
static inline short adpcm_yamaha_decode_nibble( audio_channel_t c, 
nkeynes@736
   296
                                                unsigned char nibble )
nkeynes@66
   297
{
nkeynes@66
   298
    if( c->adpcm_step == 0 ) {
nkeynes@66
   299
        c->adpcm_predict = 0;
nkeynes@66
   300
        c->adpcm_step = 127;
nkeynes@66
   301
    }
nkeynes@66
   302
nkeynes@66
   303
    c->adpcm_predict += (c->adpcm_step * yamaha_difflookup[nibble]) >> 3;
nkeynes@66
   304
    CLAMP_TO_SHORT(c->adpcm_predict);
nkeynes@66
   305
    c->adpcm_step = (c->adpcm_step * yamaha_indexscale[nibble]) >> 8;
nkeynes@66
   306
    c->adpcm_step = CLAMP(c->adpcm_step, 127, 24567);
nkeynes@66
   307
    return c->adpcm_predict;
nkeynes@66
   308
}
nkeynes@66
   309
nkeynes@66
   310
/*************************** Sample mixer *****************************/
nkeynes@66
   311
nkeynes@66
   312
/**
nkeynes@66
   313
 * Mix a single output sample.
nkeynes@66
   314
 */
nkeynes@73
   315
void audio_mix_samples( int num_samples )
nkeynes@66
   316
{
nkeynes@66
   317
    int i, j;
nkeynes@73
   318
    int32_t result_buf[num_samples][2];
nkeynes@73
   319
nkeynes@73
   320
    memset( &result_buf, 0, sizeof(result_buf) );
nkeynes@66
   321
nkeynes@465
   322
    for( i=0; i < AUDIO_CHANNEL_COUNT; i++ ) {
nkeynes@697
   323
        audio_channel_t channel = &audio.channels[i];
nkeynes@697
   324
        if( channel->active ) {
nkeynes@697
   325
            int32_t sample;
nkeynes@697
   326
            int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
nkeynes@697
   327
            int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
nkeynes@697
   328
            switch( channel->sample_format ) {
nkeynes@697
   329
            case AUDIO_FMT_16BIT:
nkeynes@697
   330
                for( j=0; j<num_samples; j++ ) {
nkeynes@1089
   331
                    sample = *(int16_t *)(aica_main_ram + ((channel->start + channel->posn*2)&AUDIO_MEM_MASK));
nkeynes@697
   332
                    result_buf[j][0] += sample * vol_left;
nkeynes@697
   333
                    result_buf[j][1] += sample * vol_right;
nkeynes@697
   334
nkeynes@697
   335
                    channel->posn_left += channel->sample_rate;
nkeynes@697
   336
                    while( channel->posn_left > audio.output_rate ) {
nkeynes@697
   337
                        channel->posn_left -= audio.output_rate;
nkeynes@697
   338
                        channel->posn++;
nkeynes@697
   339
nkeynes@697
   340
                        if( channel->posn == channel->end ) {
nkeynes@697
   341
                            if( channel->loop ) {
nkeynes@697
   342
                                channel->posn = channel->loop_start;
nkeynes@697
   343
                                channel->loop = LOOP_LOOPED;
nkeynes@697
   344
                            } else {
nkeynes@697
   345
                                audio_stop_channel(i);
nkeynes@697
   346
                                j = num_samples;
nkeynes@697
   347
                                break;
nkeynes@697
   348
                            }
nkeynes@697
   349
                        }
nkeynes@697
   350
                    }
nkeynes@697
   351
                }
nkeynes@697
   352
                break;
nkeynes@697
   353
            case AUDIO_FMT_8BIT:
nkeynes@697
   354
                for( j=0; j<num_samples; j++ ) {
nkeynes@1089
   355
                    sample = (*(int8_t *)(aica_main_ram + ((channel->start + channel->posn)&AUDIO_MEM_MASK))) << 8;
nkeynes@697
   356
                    result_buf[j][0] += sample * vol_left;
nkeynes@697
   357
                    result_buf[j][1] += sample * vol_right;
nkeynes@697
   358
nkeynes@697
   359
                    channel->posn_left += channel->sample_rate;
nkeynes@697
   360
                    while( channel->posn_left > audio.output_rate ) {
nkeynes@697
   361
                        channel->posn_left -= audio.output_rate;
nkeynes@697
   362
                        channel->posn++;
nkeynes@697
   363
nkeynes@697
   364
                        if( channel->posn == channel->end ) {
nkeynes@697
   365
                            if( channel->loop ) {
nkeynes@697
   366
                                channel->posn = channel->loop_start;
nkeynes@697
   367
                                channel->loop = LOOP_LOOPED;
nkeynes@697
   368
                            } else {
nkeynes@697
   369
                                audio_stop_channel(i);
nkeynes@697
   370
                                j = num_samples;
nkeynes@697
   371
                                break;
nkeynes@697
   372
                            }
nkeynes@697
   373
                        }
nkeynes@697
   374
                    }
nkeynes@697
   375
                }
nkeynes@697
   376
                break;
nkeynes@697
   377
            case AUDIO_FMT_ADPCM:
nkeynes@697
   378
                for( j=0; j<num_samples; j++ ) {
nkeynes@697
   379
                    sample = (int16_t)channel->adpcm_predict;
nkeynes@697
   380
                    result_buf[j][0] += sample * vol_left;
nkeynes@697
   381
                    result_buf[j][1] += sample * vol_right;
nkeynes@697
   382
                    channel->posn_left += channel->sample_rate;
nkeynes@697
   383
                    while( channel->posn_left > audio.output_rate ) {
nkeynes@697
   384
                        channel->posn_left -= audio.output_rate;
nkeynes@697
   385
                        channel->posn++;
nkeynes@697
   386
                        if( channel->posn == channel->end ) {
nkeynes@697
   387
                            if( channel->loop ) {
nkeynes@697
   388
                                channel->posn = channel->loop_start;
nkeynes@697
   389
                                channel->loop = LOOP_LOOPED;
nkeynes@697
   390
                                channel->adpcm_predict = 0;
nkeynes@697
   391
                                channel->adpcm_step = 0;
nkeynes@697
   392
                            } else {
nkeynes@697
   393
                                audio_stop_channel(i);
nkeynes@697
   394
                                j = num_samples;
nkeynes@697
   395
                                break;
nkeynes@697
   396
                            }
nkeynes@697
   397
                        }
nkeynes@1089
   398
                        uint8_t data = *(uint8_t *)(aica_main_ram + ((channel->start + (channel->posn>>1))&AUDIO_MEM_MASK));
nkeynes@697
   399
                        if( channel->posn&1 ) {
nkeynes@697
   400
                            adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
nkeynes@697
   401
                        } else {
nkeynes@697
   402
                            adpcm_yamaha_decode_nibble( channel, data & 0x0F );
nkeynes@697
   403
                        }
nkeynes@697
   404
                    }
nkeynes@697
   405
                }
nkeynes@697
   406
                break;
nkeynes@697
   407
            default:
nkeynes@697
   408
                break;
nkeynes@697
   409
            }
nkeynes@697
   410
        }
nkeynes@66
   411
    }
nkeynes@736
   412
nkeynes@66
   413
    /* Down-render to the final output format */
nkeynes@697
   414
    audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
nkeynes@697
   415
    if( buf->status == BUFFER_FULL ) {
nkeynes@697
   416
        buf = audio_next_write_buffer();
nkeynes@697
   417
        if( buf == NULL ) { // no available space
nkeynes@697
   418
            return;
nkeynes@697
   419
        }
nkeynes@697
   420
    }
nkeynes@736
   421
nkeynes@697
   422
    switch( audio.output_format & AUDIO_FMT_SAMPLE_MASK ) {
nkeynes@697
   423
    case AUDIO_FMT_FLOAT: {
nkeynes@697
   424
        float scale = 1.0/SHRT_MAX;
nkeynes@697
   425
        float *data = (float *)&buf->data[buf->posn];
nkeynes@697
   426
        for( j=0; j<num_samples; j++ ) {
nkeynes@697
   427
            *data++ = scale * (result_buf[j][0] >> 6);
nkeynes@697
   428
            *data++ = scale * (result_buf[j][1] >> 6);
nkeynes@697
   429
            buf->posn += 8;
nkeynes@697
   430
            if( buf->posn == buf->length ) {
nkeynes@697
   431
                buf = audio_next_write_buffer();
nkeynes@697
   432
                if( buf == NULL ) {
nkeynes@697
   433
                    break;
nkeynes@697
   434
                }
nkeynes@697
   435
                data = (float *)&buf->data[0];
nkeynes@697
   436
            }
nkeynes@697
   437
        }
nkeynes@697
   438
        break;
nkeynes@697
   439
    }
nkeynes@697
   440
    case AUDIO_FMT_16BIT: {
nkeynes@697
   441
        int16_t *data = (int16_t *)&buf->data[buf->posn];
nkeynes@697
   442
        for( j=0; j < num_samples; j++ ) {
nkeynes@697
   443
            *data++ = (int16_t)(result_buf[j][0] >> 6);
nkeynes@697
   444
            *data++ = (int16_t)(result_buf[j][1] >> 6);	
nkeynes@697
   445
            buf->posn += 4;
nkeynes@697
   446
            if( buf->posn == buf->length ) {
nkeynes@697
   447
                buf = audio_next_write_buffer();
nkeynes@697
   448
                if( buf == NULL ) {
nkeynes@697
   449
                    // All buffers are full
nkeynes@697
   450
                    break;
nkeynes@697
   451
                }
nkeynes@697
   452
                data = (int16_t *)&buf->data[0];
nkeynes@697
   453
            }
nkeynes@697
   454
        }
nkeynes@697
   455
        break;
nkeynes@697
   456
    }
nkeynes@697
   457
    case AUDIO_FMT_8BIT: {
nkeynes@700
   458
        int8_t *data = (int8_t *)&buf->data[buf->posn];
nkeynes@697
   459
        for( j=0; j < num_samples; j++ ) {
nkeynes@697
   460
            *data++ = (int8_t)(result_buf[j][0] >> 16);
nkeynes@697
   461
            *data++ = (int8_t)(result_buf[j][1] >> 16);	
nkeynes@697
   462
            buf->posn += 2;
nkeynes@697
   463
            if( buf->posn == buf->length ) {
nkeynes@697
   464
                buf = audio_next_write_buffer();
nkeynes@697
   465
                if( buf == NULL ) {
nkeynes@697
   466
                    // All buffers are full
nkeynes@697
   467
                    break;
nkeynes@697
   468
                }
nkeynes@697
   469
                buf = audio.output_buffers[audio.write_buffer];
nkeynes@700
   470
                data = (int8_t *)&buf->data[0];
nkeynes@697
   471
            }
nkeynes@697
   472
        }
nkeynes@697
   473
        break;
nkeynes@697
   474
    }
nkeynes@66
   475
    }
nkeynes@66
   476
}
nkeynes@66
   477
nkeynes@66
   478
/********************** Internal AICA calls ***************************/
nkeynes@66
   479
nkeynes@66
   480
audio_channel_t audio_get_channel( int channel ) 
nkeynes@66
   481
{
nkeynes@66
   482
    return &audio.channels[channel];
nkeynes@66
   483
}
nkeynes@66
   484
nkeynes@434
   485
void audio_start_stop_channel( int channel, gboolean start )
nkeynes@434
   486
{
nkeynes@434
   487
    if( audio.channels[channel].active ) {
nkeynes@736
   488
        if( !start ) {
nkeynes@736
   489
            audio_stop_channel(channel);
nkeynes@736
   490
        }
nkeynes@434
   491
    } else if( start ) {
nkeynes@736
   492
        audio_start_channel(channel);
nkeynes@434
   493
    }
nkeynes@434
   494
}
nkeynes@434
   495
nkeynes@66
   496
void audio_stop_channel( int channel ) 
nkeynes@66
   497
{
nkeynes@66
   498
    audio.channels[channel].active = FALSE;
nkeynes@66
   499
}
nkeynes@66
   500
nkeynes@66
   501
nkeynes@66
   502
void audio_start_channel( int channel )
nkeynes@66
   503
{
nkeynes@66
   504
    audio.channels[channel].posn = 0;
nkeynes@66
   505
    audio.channels[channel].posn_left = 0;
nkeynes@66
   506
    audio.channels[channel].active = TRUE;
nkeynes@434
   507
    if( audio.channels[channel].sample_format == AUDIO_FMT_ADPCM ) {
nkeynes@736
   508
        audio.channels[channel].adpcm_step = 0;
nkeynes@736
   509
        audio.channels[channel].adpcm_predict = 0;
nkeynes@934
   510
        uint8_t data = ((uint8_t *)(aica_main_ram + audio.channels[channel].start))[0];
nkeynes@736
   511
        adpcm_yamaha_decode_nibble( &audio.channels[channel], data & 0x0F );
nkeynes@434
   512
    }
nkeynes@66
   513
}
.