~jazzva/fakenes/ubuntu

« back to all changes in this revision

Viewing changes to src/audio.cpp

  • Committer: Sasa Bodiroza
  • Date: 2007-08-15 05:37:49 UTC
  • Revision ID: jazzva@gmail.com-20070815053749-76l0xj66tzgt290p
Upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FakeNES - A free, portable, Open Source NES emulator.
 
2
 
 
3
   audio.cpp: Implementation of the audio interface.
 
4
 
 
5
   Copyright (c) 2001-2007, FakeNES Team.
 
6
   This is free software.  See 'LICENSE' for details.
 
7
   You must read and accept the license prior to use. */
 
8
 
 
9
#include <allegro.h>
 
10
#include <cstdlib>
 
11
#include <cstring>
 
12
#include <vector>
 
13
#include "apu.h"
 
14
#include "audio.h"
 
15
#include "audio_int.h"
 
16
#include "audiolib.h"
 
17
#include "common.h"
 
18
#include "debug.h"
 
19
#include "gui.h"
 
20
#include "timing.h"
 
21
#include "types.h"
 
22
 
 
23
/* TODO: Fix WAV recording stuff up to work properly on big-endian platforms(currently it produces a big-endian ordered
 
24
         WAV file, I think). */
 
25
 
 
26
 
 
27
/* Note that, whenever something is marked as "Read-only outside of the audio system", it means that it should NEVER be
 
28
   modified outside of audio.c, audio.h(inline functions only), and audiolib.c.
 
29
   If such variables are modified, it could cause problems. */
 
30
 
 
31
/* Also note that in the context used here, 'frames' refers to a single sample (mono) or sample pair (stereo) - not a whole
 
32
   frame of NES audio as the name might suggest. ;) (A concept that the audio system actually does not understand.) */
 
33
 
 
34
// Audio options.  Usually these work more as strong suggestions rather than hard requirements.
 
35
audio_options_t audio_options = {
 
36
   TRUE,                    // Enable output
 
37
   AUDIO_SUBSYSTEM_ALLEGRO, // Subsystem
 
38
   -1,                      // Prefered sample rate (Autodetect)
 
39
   -1,                      // Prefered buffer length(ms) (Autodetect)
 
40
};
 
41
 
 
42
// Number of channels.  This usually comes from the APU options.  Read-only outside of the audio system.
 
43
int audio_channels = 0;
 
44
 
 
45
// Sample rate.  Set by the audio driver.  Read-only outside of the audio system.
 
46
int audio_sample_rate = 0;
 
47
 
 
48
// Bits per sample.  Set by the audio driver.  Read-only outside of the audio system.
 
49
int audio_sample_bits = 0;
 
50
 
 
51
/* Whether samples are signed or not.  Set by the audio driver.  Read-only outside of the audio system.
 
52
 
 
53
   This only affects the format of samples that are sent to the active subsystem via the audio buffer; it does not affect
 
54
   samples in the queue (which should always be unsigned; see below). */
 
55
BOOL audio_signed_samples = FALSE;
 
56
 
 
57
// Buffer length (in milliseconds).  Set by the audio driver.  Read-only outside of the audio system.
 
58
int audio_buffer_length_ms = 0;
 
59
 
 
60
// Buffer sizes.  Read-only outside of the audio system.
 
61
unsigned audio_buffer_size_frames = 0;  // numframes
 
62
unsigned audio_buffer_size_samples = 0; // numframes*numchannels
 
63
unsigned audio_buffer_size_bytes = 0;   // numframes*numchannels*(bitspersample/8)
 
64
 
 
65
/* FIFO queue to hold audio samples until they can be transfered to the audio buffer.
 
66
   Read-only outside of the audio system.
 
67
 
 
68
   Samples in the queue should be stored in unsigned 16-bit format.  Any pre-processing such as stereo blending must be done
 
69
   prior to storing the samples to the queue, as it won't be done automatically.
 
70
 
 
71
   Use audio_queue_sample() (defined in audio.h) to write to the queue in a performance-efficient way.  However, since the
 
72
   queue is stored as a vector, that function will only work from C++ code. */
 
73
std::vector<uint16> audioQueue;
 
74
 
 
75
// Audio buffer, for transfering samples from the queue to the active subsystem in the appropriate format.
 
76
static void* audioBuffer = null;
 
77
 
 
78
// The number of frames currently present in the audio buffer.
 
79
static unsigned audioBufferedFrames = 0;
 
80
 
 
81
// Frame rate counter.
 
82
volatile int audio_fps = 0;
 
83
 
 
84
// Variables for the WAV writer(see bottom).
 
85
static FILE* wavFile = null;
 
86
static unsigned wavSize = 0;
 
87
 
 
88
/* Visualization buffer.  This is an actual ring buffer (not a fake one like the audio buffer) into which all data from the
 
89
   audio queue eventually passes when visualization is enabled. */
 
90
static unsigned audioVisBufferSize = 0;
 
91
static uint16* audioVisBuffer = null;
 
92
static unsigned audioVisBufferOffset = 0;
 
93
static unsigned audioVisBufferHead = 0;
 
94
static unsigned audioVisBufferTail = 0;
 
95
 
 
96
void audio_load_config(void)
 
97
{
 
98
   DEBUG_PRINTF("audio_load_config()\n");
 
99
 
 
100
   audio_options.enable_output         = true_or_false(get_config_int("audio", "enable_output", audio_options.enable_output));
 
101
   audio_options.subsystem             = get_config_int("audio", "subsystem",        audio_options.subsystem);
 
102
   audio_options.sample_rate_hint      = get_config_int("audio", "sample_rate",      audio_options.sample_rate_hint);
 
103
   audio_options.buffer_length_ms_hint = get_config_int("audio", "buffer_length_ms", audio_options.buffer_length_ms_hint);
 
104
}
 
105
 
 
106
void audio_save_config(void)
 
107
{
 
108
   DEBUG_PRINTF("audio_save_config()\n");
 
109
 
 
110
   set_config_int("audio", "enable_output",    (audio_options.enable_output ? 1 : 0));
 
111
   set_config_int("audio", "subsystem",        audio_options.subsystem);
 
112
   set_config_int("audio", "sample_rate",      audio_options.sample_rate_hint);
 
113
   set_config_int("audio", "buffer_length_ms", audio_options.buffer_length_ms_hint);
 
114
}
 
115
 
 
116
int audio_init(void)
 
117
{
 
118
   DEBUG_PRINTF("audio_init()\n");
 
119
 
 
120
   if(!audio_options.enable_output) {
 
121
      // Audio output is disabled - bail out.
 
122
      return 0;
 
123
   }
 
124
 
 
125
   // Determine number of channels.
 
126
   audio_channels = (apu_options.stereo ? 2 : 1);
 
127
 
 
128
   // Initialize audio library.
 
129
   int result = audiolib_init();
 
130
   if(result != 0) {
 
131
      WARN("I'm sorry, but I couldn't find a suitable audio driver. :<\n"
 
132
           "\n"
 
133
           "Possible causes for this problem:\n"
 
134
           "  - There is no sound hardware present\n"
 
135
           "  - The installed sound drivers are not working properly\n"
 
136
           "  - The sound API (e.g Allegro or OpenAL) is not cooperating for some reason\n"
 
137
           "  - The sound system is already in use by another application\n"
 
138
           "\n"
 
139
           "Usually, the sound system is just in use by another application.\n"
 
140
           "Try again in a few minutes. :)");
 
141
 
 
142
      audio_exit();
 
143
      return (8 + result);
 
144
   }
 
145
 
 
146
   // Determine buffer sizes.
 
147
   audio_buffer_size_frames = (unsigned)ROUND((audio_sample_rate / 1000.0) * audio_buffer_length_ms);
 
148
   audio_buffer_size_samples = (audio_buffer_size_frames * audio_channels);
 
149
   audio_buffer_size_bytes = (audio_buffer_size_samples * (audio_sample_bits / 8));
 
150
 
 
151
   // Allocate buffer.
 
152
   audioBuffer = malloc(audio_buffer_size_bytes);
 
153
   if(!audioBuffer) {
 
154
      WARN("Couldn't allocate audio buffer (out of memory?)");
 
155
      audio_exit();
 
156
      return 1;
 
157
   }
 
158
 
 
159
   // Clear buffer.
 
160
   memset(audioBuffer, 0, audio_buffer_size_bytes);
 
161
 
 
162
   // Begin playing.
 
163
   result = audiolib_open_stream();
 
164
   if(result != 0) {
 
165
      WARN("Call to audiolib_open_stream() failed");
 
166
      audio_exit();
 
167
      return (16 + result);
 
168
   }
 
169
 
 
170
   // Return success.
 
171
   return 0;
 
172
}
 
173
 
 
174
void audio_exit(void)
 
175
{
 
176
   DEBUG_PRINTF("audio_exit()\n");
 
177
 
 
178
   // Deinitialize audio library.
 
179
   audiolib_exit();
 
180
 
 
181
   if(audioBuffer) {
 
182
      // Destroy audio buffer.
 
183
      free(audioBuffer);
 
184
      audioBuffer = null;
 
185
      // Clear the frame counter.
 
186
      audioBufferedFrames = 0;
 
187
   }
 
188
 
 
189
   if(audioQueue.size() > 0) {
 
190
      // Clear queue.
 
191
      audioQueue.clear();
 
192
   }
 
193
 
 
194
   if(wavFile)
 
195
      audio_close_wav();
 
196
 
 
197
   if(audioVisBuffer)
 
198
      audio_visclose();
 
199
}
 
200
 
 
201
void audio_update(void)
 
202
{
 
203
   // Audio update function, called once per scanline. 
 
204
   DEBUG_PRINTF("audio_update()\n");
 
205
 
 
206
   if(!audio_options.enable_output)
 
207
      return;
 
208
 
 
209
   // Check if the buffer is full.
 
210
   if(audioBufferedFrames == audio_buffer_size_frames) {
 
211
      // See if we can update the driver buffer yet.
 
212
      void* audiolibBuffer = audiolib_get_buffer(audioBuffer);
 
213
      if(audiolibBuffer) {
 
214
         if(audiolibBuffer != audioBuffer) {
 
215
            // Copy to external buffer.
 
216
            memcpy(audiolibBuffer, audioBuffer, audio_buffer_size_bytes);
 
217
         }
 
218
 
 
219
         // Let the subsystem have it.
 
220
         audiolib_free_buffer(audiolibBuffer);
 
221
 
 
222
         // Empty the internal buffer.
 
223
         audioBufferedFrames = 0;
 
224
 
 
225
         audio_fps += audio_buffer_size_frames;
 
226
      }
 
227
      else {
 
228
         /* This code simulates a ring buffer for when the output system can't keep up with the emulation (e.g while using
 
229
            fast forward), by scrapping the oldest data in the buffer and adding the new data(see below).
 
230
 
 
231
            This is functionally identical to using an actual ring buffer, though not nearly as efficient. */
 
232
 
 
233
         // Determine how many frames are available in the queue.
 
234
         const unsigned queuedFrames = (audioQueue.size() / audio_channels);
 
235
         if(queuedFrames > 0) {
 
236
            // Determine how many frames we want to make room for.
 
237
            const unsigned framesToAdd = min(queuedFrames, audio_buffer_size_frames);
 
238
            // Make room for the frames in the buffer.
 
239
            const unsigned framesToMove = (audioBufferedFrames - framesToAdd);
 
240
            if(framesToMove > 0) {
 
241
               const unsigned copyBase = (((audioBufferedFrames - framesToMove) * audio_channels) * (audio_sample_bits / 8));
 
242
               const unsigned samplesToMove = (framesToMove * audio_channels);
 
243
               const unsigned bytesToMove = (samplesToMove * (audio_sample_bits / 8));
 
244
 
 
245
               uint8* buffer = (uint8*)audioBuffer;
 
246
               memcpy(&buffer[0], &buffer[copyBase], bytesToMove);
 
247
            }
 
248
 
 
249
            audioBufferedFrames -= framesToAdd;
 
250
         }
 
251
      }
 
252
   }
 
253
 
 
254
   if(audioBufferedFrames < audio_buffer_size_frames) {
 
255
      // Determine how many frames are available in the queue.
 
256
      const unsigned queuedFrames = (audioQueue.size() / audio_channels);
 
257
      if(queuedFrames > 0) {
 
258
         // Determine how many frames are available in the buffer.
 
259
         const unsigned bufferableFrames = (audio_buffer_size_frames - audioBufferedFrames);
 
260
         // Determine the number of frames to copy to the buffer.
 
261
         const unsigned framesToCopy = min(queuedFrames, bufferableFrames);
 
262
 
 
263
         // Copy frames to the buffer.
 
264
         for(unsigned frame = 0; frame < framesToCopy; frame++) {
 
265
            // Read/write base addresses (read from queue, write to buffer).
 
266
            const unsigned readBase = (frame * audio_channels);
 
267
            // audioBufferedFrames changes within the loop(see below), so all we have to do is use it as a write pointer.
 
268
            const unsigned writeBase = (audioBufferedFrames * audio_channels);
 
269
 
 
270
            for(int channel = 0; channel < audio_channels; channel++) {
 
271
               // Fetch a sample from the queue.
 
272
               uint16 sample = audioQueue[readBase + channel];
 
273
 
 
274
               if(audioVisBuffer) {
 
275
                  // Buffer it for visualization.
 
276
                  audioVisBuffer[audioVisBufferOffset] = sample;
 
277
                  audioVisBufferOffset++;
 
278
                  if(audioVisBufferOffset > audioVisBufferTail) { 
 
279
                     // The buffer has filled up.
 
280
                     if(audioVisBufferOffset > (audioVisBufferSize - 1))
 
281
                        audioVisBufferOffset = 0;
 
282
 
 
283
                     // Move head and tail, wrapping around if neccessary.
 
284
                     audioVisBufferHead++;
 
285
                     if(audioVisBufferHead > (audioVisBufferSize - 1))
 
286
                        audioVisBufferHead = 0;
 
287
 
 
288
                     audioVisBufferTail++;
 
289
                     if(audioVisBufferTail > (audioVisBufferSize - 1))
 
290
                        audioVisBufferTail = 0;
 
291
                  }
 
292
               }
 
293
 
 
294
               if(audio_signed_samples) {
 
295
                  // Convert to signed.
 
296
                  sample ^= 0x8000;
 
297
               }
 
298
 
 
299
               /* Determine our write offset for the buffer (this remains constant regardless of the value of sample_bits
 
300
                  since we cast the buffer to an appropriately sized data type). */
 
301
               const unsigned writeOffset = (writeBase + channel);
 
302
 
 
303
               // Write our sample to the buffer.
 
304
               switch(audio_sample_bits) {
 
305
                  case 8: {
 
306
                     // Reduce to 8 bits.
 
307
                     sample >>= 8;
 
308
 
 
309
                     uint8* buffer = (uint8*)audioBuffer;
 
310
                     buffer[writeOffset] = sample;
 
311
 
 
312
                     if(wavFile) {
 
313
                        if(audio_signed_samples) {
 
314
                           // Convert to unsigned.
 
315
                           sample ^= 0x80;
 
316
                        }
 
317
 
 
318
                        putc(sample, wavFile);
 
319
                        wavSize++;
 
320
                     }
 
321
 
 
322
                     break;
 
323
                  }
 
324
 
 
325
                  case 16: {
 
326
                     uint16* buffer = (uint16*)audioBuffer;
 
327
                     buffer[writeOffset] = sample;
 
328
 
 
329
                     if(wavFile) {
 
330
                        if(!audio_signed_samples) {
 
331
                           // Convert to signed.
 
332
                           sample ^= 0x8000;
 
333
                        }
 
334
 
 
335
                        putc((sample & 0xFF), wavFile);
 
336
                        putc(((sample & 0xFF00) >> 8), wavFile);
 
337
 
 
338
                        wavSize += 2;
 
339
                     }
 
340
 
 
341
                     break;
 
342
                  }
 
343
 
 
344
                  default:
 
345
                     WARN_GENERIC();
 
346
               }
 
347
            }
 
348
 
 
349
            // Increment frame counter.
 
350
            audioBufferedFrames++;
 
351
         }
 
352
 
 
353
         // Determine how many samples we copied.
 
354
         const unsigned samplesCopied = (framesToCopy * audio_channels);
 
355
         const unsigned samplesRemaining = (audioQueue.size() - samplesCopied);
 
356
         /* Removed copied samples from the queue.
 
357
            Thanks KittyCat! =^-^= */
 
358
         memcpy(&audioQueue[0], &audioQueue[samplesCopied], (sizeof(uint16) * samplesRemaining));
 
359
         audioQueue.resize(samplesRemaining);
 
360
      }
 
361
   }
 
362
 
 
363
   // Check if the buffer is full.
 
364
   if(audioBufferedFrames == audio_buffer_size_frames) {
 
365
      // See if we can update the driver buffer yet.
 
366
      void* audiolibBuffer = audiolib_get_buffer(audioBuffer);
 
367
      if(audiolibBuffer) {
 
368
         if(audiolibBuffer != audioBuffer) {
 
369
            // Copy to external buffer.
 
370
            memcpy(audiolibBuffer, audioBuffer, audio_buffer_size_bytes);
 
371
         }
 
372
 
 
373
         // Let the subsystem have it.
 
374
         audiolib_free_buffer(audiolibBuffer);
 
375
 
 
376
         // Empty the internal buffer.
 
377
         audioBufferedFrames = 0;
 
378
 
 
379
         audio_fps += audio_buffer_size_frames;
 
380
      }
 
381
   }
 
382
}
 
383
 
 
384
void audio_suspend(void)
 
385
{
 
386
   DEBUG_PRINTF("audio_suspend()\n");
 
387
 
 
388
   if (!audio_options.enable_output)
 
389
      return;
 
390
 
 
391
   audiolib_suspend();
 
392
}
 
393
 
 
394
void audio_resume(void)
 
395
{
 
396
   DEBUG_PRINTF("audio_resume()\n");
 
397
 
 
398
   if (!audio_options.enable_output)
 
399
      return;
 
400
 
 
401
   audiolib_resume();
 
402
}
 
403
 
 
404
// --- WAV recording functions. ---
 
405
typedef struct _WAVRIFFTypeChunk {
 
406
   uint32 chunkID;
 
407
   int32 chunkSize;
 
408
   uint32 riffType;
 
409
 
 
410
} WAVRIFFTypeChunk;
 
411
 
 
412
typedef struct _WAVFormatChunk {
 
413
   uint32 chunkID;
 
414
   int32 chunkSize;
 
415
   int16 formatTag;
 
416
   uint16 channels;
 
417
   uint32 samplesPerSec;
 
418
   uint32 avgBytesPerSec;
 
419
   uint16 blockAlign;
 
420
   uint16 bitsPerSample;
 
421
 
 
422
} WAVFormatChunk;
 
423
 
 
424
typedef struct _WAVDataChunk {
 
425
   uint32 chunkID;
 
426
   int32 chunkSize;
 
427
 
 
428
} WAVDataChunk;
 
429
 
 
430
#define WAV_ID(a,b,c,d) ((d << 24) | (c << 16) | (b << 8) | a)
 
431
 
 
432
#define WAV_HEADER_SIZE (sizeof(WAVRIFFTypeChunk) + \
 
433
                         sizeof(WAVFormatChunk) + \
 
434
                         sizeof(WAVDataChunk))
 
435
 
 
436
int audio_open_wav(const UCHAR* filename)
 
437
{
 
438
   /* Open file. */
 
439
   wavFile = fopen(filename, "wb");
 
440
   if(!wavFile)
 
441
      return 1;
 
442
 
 
443
   // Skip header space.
 
444
   fseek(wavFile, WAV_HEADER_SIZE, SEEK_SET);
 
445
 
 
446
   // Clear size counter.
 
447
   wavSize = 0;
 
448
 
 
449
   // Return success.
 
450
   return 0;
 
451
}
 
452
 
 
453
void audio_close_wav(void)
 
454
{
 
455
   if(wavFile) {
 
456
      // Write header.
 
457
      fseek(wavFile, 0, SEEK_SET);
 
458
 
 
459
      WAVRIFFTypeChunk riff;
 
460
      riff.chunkID = WAV_ID('R','I','F','F');
 
461
      riff.chunkSize = ((WAV_HEADER_SIZE + wavSize) - 8);
 
462
      riff.riffType = WAV_ID('W','A','V','E');
 
463
      fwrite(&riff, sizeof(riff), 1, wavFile);
 
464
 
 
465
      WAVFormatChunk fmt;
 
466
      fmt.chunkID = WAV_ID('f','m','t',' ');
 
467
      fmt.chunkSize = (sizeof(fmt) - 8);
 
468
      fmt.formatTag = 1; // No compression.
 
469
      fmt.channels = audio_channels;
 
470
      fmt.samplesPerSec = audio_sample_rate;
 
471
      fmt.avgBytesPerSec = ((audio_sample_rate * audio_channels) * (audio_sample_bits / 8));
 
472
      fmt.blockAlign = (audio_channels * (audio_sample_bits / 8));
 
473
      fmt.bitsPerSample = audio_sample_bits;
 
474
      fwrite(&fmt,  sizeof(fmt),  1, wavFile);
 
475
      
 
476
      WAVDataChunk data;
 
477
      data.chunkID = WAV_ID('d','a','t','a');
 
478
      data.chunkSize = ((sizeof(data) + wavSize) - 8);
 
479
      fwrite(&data, sizeof(data), 1, wavFile);
 
480
 
 
481
      // Close file.
 
482
      fclose(wavFile);
 
483
      wavFile = null;
 
484
      // Clear counter.
 
485
      wavSize = 0;
 
486
   }
 
487
}
 
488
 
 
489
// --- Visualization support ---
 
490
void audio_visopen(unsigned num_frames)
 
491
{
 
492
   // Attempts to open a visualization buffer (no error checking - use audio_get_visdata() for that instead).
 
493
   audioVisBufferSize = (num_frames * audio_channels);
 
494
   audioVisBuffer = new uint16[audioVisBufferSize];
 
495
}
 
496
 
 
497
void audio_visclose(void)
 
498
{
 
499
   if(audioVisBuffer) {
 
500
      // Destroy visualization buffer.
 
501
      delete[] audioVisBuffer;
 
502
      audioVisBuffer = null;
 
503
   }
 
504
}
 
505
 
 
506
UINT16* audio_get_visdata(void)
 
507
{
 
508
   // Gets visualization data from the visualization buffer.  Used by the NSF player, but might be used by the normal
 
509
   // HUD later on.
 
510
   // Remember to delete[] it when you're done with it!
 
511
   
 
512
   if(!audioVisBuffer) {
 
513
      WARN_GENERIC();
 
514
      return null;
 
515
   }
 
516
 
 
517
   UINT16* visdata = new UINT16[audioVisBufferSize];
 
518
   if(!visdata) {
 
519
      WARN_GENERIC();
 
520
      return null;
 
521
   }
 
522
 
 
523
   memcpy(&visdata[0], &audioVisBuffer[0], (audioVisBufferSize * sizeof(uint16)));
 
524
 
 
525
   return visdata;
 
526
}