diff --git a/desmume/src/mic.cpp b/desmume/src/mic.cpp index 50ce31f92..ac9368e0a 100644 --- a/desmume/src/mic.cpp +++ b/desmume/src/mic.cpp @@ -1,6 +1,6 @@ /* mic.cpp - this file is part of DeSmuME * - * Copyright (C) 2009 DeSmuME Team + * Copyright (C) 2009-2011 DeSmuME Team * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,37 +20,178 @@ #ifndef WIN32 -#include "types.h" +#include #include "mic.h" +#include "NDSSystem.h" #include "readwrite.h" -#include "emufile.h" -static BOOL silence = TRUE; +#define MIC_NULL_SAMPLE_VALUE 0 +#define MIC_MAX_BUFFER_SAMPLES 320 +#define MIC_BUFFER_SIZE (sizeof(u8) * MIC_MAX_BUFFER_SAMPLES) +#define NUM_INTERNAL_NOISE_SAMPLES 32 -BOOL Mic_Init() +static u8 *micSampleBuffer = NULL; // Pointer to the internal sample buffer. +static u8 *micReadPosition = NULL; // Pointer to the read position of the internal sample buffer. +static u8 *micWritePosition = NULL; // Pointer to the write position of the internal sample buffer. +static unsigned int micBufferFillCount; // The number of readable samples in the internal sample buffer. + +static void Mic_BufferClear(void) { - return TRUE; + if (micSampleBuffer == NULL) { + return; + } + + memset(micSampleBuffer, MIC_NULL_SAMPLE_VALUE, MIC_BUFFER_SIZE); + micReadPosition = micSampleBuffer; + micWritePosition = micSampleBuffer; + micBufferFillCount = 0; } -void Mic_Reset() +BOOL Mic_Init(void) { + BOOL result = FALSE; + + u8 *newBuffer = (u8 *)malloc(MIC_BUFFER_SIZE); + if (newBuffer == NULL) { + return result; + } + + micSampleBuffer = newBuffer; + Mic_BufferClear(); + result = TRUE; + + return result; } -void Mic_DeInit() +void Mic_DeInit(void) { + free(micSampleBuffer); + micSampleBuffer = NULL; } -u8 Mic_ReadSample() +void Mic_Reset(void) { - if (silence) - return 0; + *micReadPosition = MIC_NULL_SAMPLE_VALUE; + micWritePosition = micReadPosition; + micBufferFillCount = 0; +} - return 150; +static bool Mic_GetActivate(void) +{ + return NDS_getFinalUserInput().mic.micButtonPressed; +} + +static bool Mic_IsBufferFull(void) +{ + return (micBufferFillCount >= MIC_MAX_BUFFER_SAMPLES); +} + +static bool Mic_IsBufferEmpty(void) +{ + return (micBufferFillCount == 0); +} + +static u8 Mic_DefaultBufferRead(void) +{ + u8 theSample = MIC_NULL_SAMPLE_VALUE; + + if (micSampleBuffer == NULL) { + return theSample; + } + + theSample = *micReadPosition; + + if (Mic_IsBufferEmpty()) { + return theSample; + } + + micReadPosition++; + micBufferFillCount--; + + // Move the pointer back to start if we reach the end of the memory block. + if (micReadPosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { + micReadPosition = micSampleBuffer; + } + + return theSample; +} + +u8 Mic_ReadSample(void) +{ + // All mic modes other than Physical must have the mic hotkey pressed in order + // to work. + if (CommonSettings.micMode != TCommonSettings::Physical && !Mic_GetActivate()) { + return MIC_NULL_SAMPLE_VALUE; + } + + return Mic_DefaultBufferRead(); +} + +static void Mic_DefaultBufferWrite(u8 theSample) +{ + if (micSampleBuffer == NULL || Mic_IsBufferFull()) { + return; + } + + *micWritePosition = theSample; + micWritePosition++; + micBufferFillCount++; + + // Move the pointer back to start if we reach the end of the memory block. + if (micWritePosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { + micWritePosition = micSampleBuffer; + } +} + +static u8 Mic_GenerateInternalNoiseSample(void) +{ + const u8 noiseSample[NUM_INTERNAL_NOISE_SAMPLES] = + { + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF, + 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01 + }; + static unsigned int i = 0; + + if (++i >= NUM_INTERNAL_NOISE_SAMPLES) { + i = 0; + } + + return noiseSample[i]; +} + +static u8 Mic_GenerateWhiteNoiseSample(void) +{ + return (u8)(rand() & 0xFF); +} + +static u8 Mic_GenerateNullSample(void) +{ + return MIC_NULL_SAMPLE_VALUE; } void Mic_DoNoise(BOOL noise) { - silence = !noise; + u8 (*generator) (void) = NULL; + + if (micSampleBuffer == NULL) { + return; + } + + if (!noise) { + generator = &Mic_GenerateNullSample; + } else if (CommonSettings.micMode == TCommonSettings::InternalNoise) { + generator = &Mic_GenerateInternalNoiseSample; + } else if (CommonSettings.micMode == TCommonSettings::Random) { + generator = &Mic_GenerateWhiteNoiseSample; + } + + if (generator == NULL) { + return; + } + + while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) { + Mic_DefaultBufferWrite(generator()); + } } void mic_savestate(EMUFILE* os) diff --git a/desmume/src/mic.h b/desmume/src/mic.h index ae85a901b..a7fae7ed5 100644 --- a/desmume/src/mic.h +++ b/desmume/src/mic.h @@ -1,6 +1,6 @@ /* mic.h - this file is part of DeSmuME * - * Copyright (C) 2009 DeSmuME Team + * Copyright (C) 2009-2011 DeSmuME Team * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,10 @@ #ifndef MIC_H #define MIC_H + #include #include "emufile.h" +#include "types.h" #ifdef WIN32 static char MicSampleName[256]; @@ -34,12 +36,12 @@ extern int MicDisplay; void Mic_DoNoise(BOOL); #endif -BOOL Mic_Init(); -void Mic_Reset(); -void Mic_DeInit(); -u8 Mic_ReadSample(); +BOOL Mic_Init(void); +void Mic_Reset(void); +void Mic_DeInit(void); +u8 Mic_ReadSample(void); void mic_savestate(EMUFILE* os); bool mic_loadstate(EMUFILE* is, int size); -#endif +#endif // MIC_H