From ec17ea864fb071c0ab19a09d5ffa67f2067421c0 Mon Sep 17 00:00:00 2001 From: clobber Date: Fri, 7 Aug 2015 03:44:38 -0500 Subject: [PATCH] Refactor sound --- ProSystem.xcodeproj/project.pbxproj | 2 + ProSystemGameCore.mm | 81 +---- core/Sound.cpp | 443 ++++------------------------ core/Sound.h | 27 +- 4 files changed, 78 insertions(+), 475 deletions(-) diff --git a/ProSystem.xcodeproj/project.pbxproj b/ProSystem.xcodeproj/project.pbxproj index 2b5e2a0..38d00be 100644 --- a/ProSystem.xcodeproj/project.pbxproj +++ b/ProSystem.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ /* Begin PBXBuildFile section */ 82EC409F0FD9EC420017FC19 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 82EC409E0FD9EC420017FC19 /* libz.dylib */; }; + 8794D9691B74713300897F57 /* Sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941F59AF17A6189D0005D7EA /* Sound.cpp */; }; 8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; }; 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; 941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 941DFB2615B6425200C6552F /* ProSystemGameCore.mm */; }; @@ -435,6 +436,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8794D9691B74713300897F57 /* Sound.cpp in Sources */, 941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */, 941F59BF17A6189D0005D7EA /* Archive.cpp in Sources */, 941F59C017A6189D0005D7EA /* Bios.cpp in Sources */, diff --git a/ProSystemGameCore.mm b/ProSystemGameCore.mm index a6e1571..5f8a6f1 100644 --- a/ProSystemGameCore.mm +++ b/ProSystemGameCore.mm @@ -33,7 +33,7 @@ #include "ProSystem.h" #include "Database.h" -//#include "Sound.h" +#include "Sound.h" #include "Palette.h" #include "Maria.h" #include "Tia.h" @@ -43,6 +43,7 @@ @interface ProSystemGameCore () { uint32_t *videoBuffer; + uint8_t *soundBuffer; int videoWidth, videoHeight; uint display_palette32[256]; byte keyboard_data[17]; @@ -66,6 +67,7 @@ static void display_ResetPalette32( ) { if((self = [super init])) { videoBuffer = (uint32_t *)malloc(320 * 292 * 4); + soundBuffer = (uint8_t *)malloc(8192); videoWidth = 320; videoHeight = 240; current = self; @@ -77,6 +79,7 @@ static void display_ResetPalette32( ) { - (void)dealloc { free(videoBuffer); + free(soundBuffer); } #pragma mark Execution @@ -153,8 +156,9 @@ static void display_ResetPalette32( ) { surface += pitch; buffer += current->videoWidth; } - - sound_Store(); + + int length = sound_Store(soundBuffer); + [[current ringBufferAtIndex:0] write:soundBuffer maxLength:length]; } - (void)resetEmulation @@ -306,75 +310,4 @@ const int ProSystemMap[] = { 3, 2, 1, 0, 4, 5, 9, 8, 7, 6, 10, 11, 13, 14, 12, 1 return prosystem_Load([fileName UTF8String]) ? YES : NO; } -static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) { - uint sampleLength = length / unitMax; - uint sampleRemain = length % unitMax; - if(sampleRemain != 0 && sampleRemain >= unit) { - sampleLength++; - } - return sampleLength; -} - -static void sound_Resample(const byte* source, byte* target, int length) { - typedef struct { - word wFormatTag; - word nChannels; - uint nSamplesPerSec; - uint nAvgBytesPerSec; - word nBlockAlign; - word wBitsPerSample; - word cbSize; - } WAVEFORMATEX; - -# define WAVE_FORMAT_PCM 0 - - static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 48000, 48000, 1, 8, 0}; - static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT; - - int measurement = sound_format.nSamplesPerSec; - int sourceIndex = 0; - int targetIndex = 0; - - int max = ( ( prosystem_frequency * prosystem_scanlines ) << 1 ); - while(targetIndex < length) { - if(measurement >= max) { - target[targetIndex++] = source[sourceIndex]; - measurement -= max; - } - else { - sourceIndex++; - measurement += sound_format.nSamplesPerSec; - } - } -} - -static void sound_Store() { -#define MAX_BUFFER_SIZE 8192 - - byte sample[MAX_BUFFER_SIZE]; - memset( sample, 0, MAX_BUFFER_SIZE ); - uint length = 48000 / prosystem_frequency; /* sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); */ /* 48000 / prosystem_frequency */ - sound_Resample(tia_buffer, sample, length); - - // Ballblazer, Commando, various homebrew and hacks - if(cartridge_pokey) { - byte pokeySample[MAX_BUFFER_SIZE]; - memset( pokeySample, 0, MAX_BUFFER_SIZE ); - sound_Resample(pokey_buffer, pokeySample, length); - for(uint index = 0; index < length; index++) { - sample[index] += pokeySample[index]; - sample[index] = sample[index] / 2; - } - } - [[current ringBufferAtIndex:0] write:sample maxLength:length]; - // Convert 8u to 16s -// for(int i = 0; i != length; i ++) -// { -// int16_t sample16 = (sample[i] << 8) - 32768; -// int16_t frame[2] = {sample16, sample16}; -// -// [[current ringBufferAtIndex:0] write:frame maxLength:2]; -// } -} - @end diff --git a/core/Sound.cpp b/core/Sound.cpp index 0f08502..8a195c9 100755 --- a/core/Sound.cpp +++ b/core/Sound.cpp @@ -23,411 +23,98 @@ // Sound.cpp // ---------------------------------------------------------------------------- #include "Sound.h" -#define SOUND_LATENCY_SCALE 4 -byte sound_latency = SOUND_LATENCY_VERY_LOW; +#define MAX_BUFFER_SIZE 8192 -static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 44100, 44100, 1, 8, 0}; -static LPDIRECTSOUND sound_dsound = NULL; -static LPDIRECTSOUNDBUFFER sound_primaryBuffer = NULL; -static LPDIRECTSOUNDBUFFER sound_buffer = NULL; -static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT; -static uint sound_counter = 0; -static bool sound_muted = false; +typedef struct +{ + uint nSamplesPerSec; + word nChannels; + word wBitsPerSample; +} SOUNDCONFIG; + +static const SOUNDCONFIG soundDefaults = {48000, 1, 8}; +static SOUNDCONFIG sound_format = soundDefaults; // ---------------------------------------------------------------------------- // GetSampleLength // ---------------------------------------------------------------------------- -static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) { - uint sampleLength = length / unitMax; - uint sampleRemain = length % unitMax; - if(sampleRemain != 0 && sampleRemain >= unit) { - sampleLength++; - } - return sampleLength; +static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) +{ + uint sampleLength = length / unitMax; + uint sampleRemain = length % unitMax; + + if(sampleRemain != 0 && sampleRemain >= unit) + { + sampleLength++; + } + + return sampleLength; } // ---------------------------------------------------------------------------- // Resample // ---------------------------------------------------------------------------- -static void sound_Resample(const byte* source, byte* target, int length) { - int measurement = sound_format.nSamplesPerSec; - int sourceIndex = 0; - int targetIndex = 0; - - while(targetIndex < length) { - if(measurement >= 31440) { - target[targetIndex++] = source[sourceIndex]; - measurement -= 31440; +static void sound_Resample(const byte *source, byte *target, int length) +{ + int measurement = sound_format.nSamplesPerSec; + int sourceIndex = 0; + int targetIndex = 0; + int max = ((prosystem_frequency * prosystem_scanlines) << 1); + + while(targetIndex < length) + { + if(measurement >= max) + { + target[targetIndex++] = source[sourceIndex]; + measurement -= max; + } + else + { + sourceIndex++; + measurement += sound_format.nSamplesPerSec; + } } - else { - sourceIndex++; - measurement += sound_format.nSamplesPerSec; - } - } -} - -// ---------------------------------------------------------------------------- -// RestoreBuffer -// ---------------------------------------------------------------------------- -static bool sound_RestoreBuffer( ) { - if(sound_buffer != NULL) { - HRESULT hr = sound_buffer->Restore( ); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND1,""); - logger_LogError("",common_Format(hr)); - return false; - } - } - return true; -} - -// ---------------------------------------------------------------------------- -// ReleaseBuffer -// ---------------------------------------------------------------------------- -static bool sound_ReleaseBuffer(LPDIRECTSOUNDBUFFER buffer) { - if(buffer != NULL) { - HRESULT hr = buffer->Release( ); - sound_buffer = NULL; - if(FAILED(hr)) { - logger_LogError(IDS_SOUND2,""); - logger_LogError("",common_Format(hr)); - return false; - } - } - return true; -} - -// ---------------------------------------------------------------------------- -// ReleaseSound -// ---------------------------------------------------------------------------- -static bool sound_ReleaseSound( ) { - if(sound_dsound != NULL) { - HRESULT hr = sound_dsound->Release( ); - sound_dsound = NULL; - if(FAILED(hr)) { - logger_LogError(IDS_SOUND3,""); - logger_LogError("",common_Format(hr)); - return false; - } - } - return true; -} - -// ---------------------------------------------------------------------------- -// Initialize -// ---------------------------------------------------------------------------- -bool sound_Initialize(HWND hWnd) { - if(hWnd == NULL) { - logger_LogError(IDS_INPUT1,""); - return false; - } - - HRESULT hr = DirectSoundCreate(NULL, &sound_dsound, NULL); - if(FAILED(hr) || sound_dsound == NULL) { - logger_LogError(IDS_SOUND4,""); - logger_LogError("",common_Format(hr)); - return false; - } - - hr = sound_dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); - if(FAILED(hr)) { - logger_LogError(IDS_INPUT6,""); - logger_LogError("",common_Format(hr)); - return false; - } - - DSBUFFERDESC primaryDesc; - primaryDesc.dwReserved = 0; - primaryDesc.dwSize = sizeof(DSBUFFERDESC); - primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; - primaryDesc.dwBufferBytes = 0; - primaryDesc.lpwfxFormat = NULL; - - hr = sound_dsound->CreateSoundBuffer(&primaryDesc, &sound_primaryBuffer, NULL); - if(FAILED(hr) || sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND5,""); - logger_LogError("",common_Format(hr)); - return false; - } - - if(!sound_SetFormat(SOUND_DEFAULT_FORMAT)) { - logger_LogError(IDS_SOUND6,""); - return false; - } - -//Leonis -sound_SetSampleRate(samplerate); - return true; -} - -// ---------------------------------------------------------------------------- -// SetFormat -// ---------------------------------------------------------------------------- -bool sound_SetFormat(WAVEFORMATEX format) { - if(sound_dsound == NULL) { - logger_LogError(IDS_SOUND7,""); - return false; - } - if(sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND8,""); - return false; - } - - HRESULT hr = sound_primaryBuffer->SetFormat(&format); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND9,""); - logger_LogError("",common_Format(hr)); - return false; - } - - DSBUFFERDESC secondaryDesc; - secondaryDesc.dwReserved = 0; - secondaryDesc.dwSize = sizeof(DSBUFFERDESC); - secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS; - secondaryDesc.dwBufferBytes = format.nSamplesPerSec; - secondaryDesc.lpwfxFormat = &format; - - hr = sound_dsound->CreateSoundBuffer(&secondaryDesc, &sound_buffer, NULL); - if(FAILED(hr) || sound_buffer == NULL) { - logger_LogError(IDS_SOUND10,""); - logger_LogError("",common_Format(hr)); - return false; - } - - sound_format = format; - return true; } // ---------------------------------------------------------------------------- // Store // ---------------------------------------------------------------------------- -bool sound_Store( ) { - if(sound_dsound == NULL) { - logger_LogError(IDS_SOUND7,""); - return false; - } - if(sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND8,""); - return false; - } - if(sound_buffer == NULL) { - logger_LogError(IDS_SOUND11,""); - return false; - } - - byte sample[1920]; - uint length = sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); - sound_Resample(tia_buffer, sample, length); - - if(cartridge_pokey) { - byte pokeySample[1920]; - sound_Resample(pokey_buffer, pokeySample, length); - for(int index = 0; index < length; index++) { - sample[index] += pokeySample[index]; - sample[index] = sample[index] / 2; +uint sound_Store(byte *out_buffer) +{ + memset(out_buffer, 0, MAX_BUFFER_SIZE); + uint length = 48000 / prosystem_frequency; // sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); + sound_Resample(tia_buffer, out_buffer, length); + + // Ballblazer, Commando, various homebrew and hacks + if(cartridge_pokey) + { + byte pokeySample[MAX_BUFFER_SIZE]; + memset(pokeySample, 0, MAX_BUFFER_SIZE); + sound_Resample(pokey_buffer, pokeySample, length); + + for(uint index = 0; index < length; index++) + { + out_buffer[index] += pokeySample[index]; + out_buffer[index] = out_buffer[index] / 2; + } } - } - - DWORD lockCount = 0; - byte* lockStream = NULL; - DWORD wrapCount = 0; - byte* wrapStream = NULL; - - HRESULT hr = sound_buffer->Lock(sound_counter, length, (void**)&lockStream, &lockCount, (void**)&wrapStream, &wrapCount, 0); - if(FAILED(hr) || lockStream == NULL) { - logger_LogError(IDS_SOUND12,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - uint bufferCounter = 0; - for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) { - lockStream[lockIndex] = sample[bufferCounter++]; - } - - for(uint wrapIndex = 0; wrapIndex < wrapCount; wrapIndex++) { - wrapStream[wrapIndex] = sample[bufferCounter++]; - } - - hr = sound_buffer->Unlock(lockStream, lockCount, wrapStream, wrapCount); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND13,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - - sound_counter += length; - if(sound_counter >= sound_format.nSamplesPerSec) { - sound_counter -= sound_format.nSamplesPerSec; - } - - return true; -} - -// ---------------------------------------------------------------------------- -// Clear -// ---------------------------------------------------------------------------- -bool sound_Clear( ) { - if(sound_dsound == NULL) { - logger_LogError(IDS_SOUND7,""); - return false; - } - if(sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND8,""); - return false; - } - if(sound_buffer == NULL) { - logger_LogError(IDS_SOUND11,""); - return false; - } - - byte* lockStream = NULL; - DWORD lockCount = 0; - HRESULT hr = sound_buffer->Lock(0, sound_format.nSamplesPerSec, (void**)&lockStream, &lockCount, NULL, NULL, DSBLOCK_ENTIREBUFFER); - if(FAILED(hr) || lockStream == NULL) { - logger_LogError(IDS_SOUND12,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - - for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) { - lockStream[lockIndex] = 0; - } - - hr = sound_buffer->Unlock(lockStream, lockCount, NULL, NULL); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND13,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - - return true; -} - -// ---------------------------------------------------------------------------- -// Play -// ---------------------------------------------------------------------------- -bool sound_Play( ) { - if(sound_dsound == NULL) { - logger_LogError(IDS_SOUND7,""); - return false; - } - if(sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND8,""); - return false; - } - if(sound_buffer == NULL) { - logger_LogError(IDS_SOUND11,""); - return false; - } - - if(!sound_muted) { - HRESULT hr = sound_buffer->SetCurrentPosition(0); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND14,""); - logger_LogError("",common_Format(hr)); - return false; - } - - hr = sound_buffer->Play(0, 0, DSBPLAY_LOOPING); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND15,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - sound_counter = (sound_format.nSamplesPerSec / prosystem_frequency) * (sound_latency * SOUND_LATENCY_SCALE); - } - return true; -} - -// ---------------------------------------------------------------------------- -// Stop -// ---------------------------------------------------------------------------- -bool sound_Stop( ) { - if(sound_dsound == NULL) { - logger_LogError(IDS_SOUND7,""); - return false; - } - if(sound_primaryBuffer == NULL) { - logger_LogError(IDS_SOUND8,""); - return false; - } - if(sound_buffer == NULL) { - logger_LogError(IDS_SOUND11,""); - return false; - } - - HRESULT hr = sound_buffer->Stop( ); - if(FAILED(hr)) { - logger_LogError(IDS_SOUND16,""); - logger_LogError("",common_Format(hr)); - if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) { - return false; - } - } - - return true; + return length; } // ---------------------------------------------------------------------------- // SetSampleRate // ---------------------------------------------------------------------------- -bool sound_SetSampleRate(uint rate) { - sound_format.nSamplesPerSec = rate; - sound_format.nAvgBytesPerSec = rate; - return sound_SetFormat(sound_format); +void sound_SetSampleRate(uint rate) +{ + sound_format.nSamplesPerSec = rate; } // ---------------------------------------------------------------------------- // GetSampleRate // ---------------------------------------------------------------------------- -uint sound_GetSampleRate( ) { - return sound_format.nSamplesPerSec; +uint sound_GetSampleRate() +{ + return sound_format.nSamplesPerSec; } - -// ---------------------------------------------------------------------------- -// SetMuted -// ---------------------------------------------------------------------------- -bool sound_SetMuted(bool muted) { - if(sound_muted != muted) { - if(!muted) { - if(!sound_Play( )) { - return false; - } - } - else { - if(!sound_Stop( )) { - return false; - } - } - sound_muted = muted; - } - return true; -} - -// ---------------------------------------------------------------------------- -// IsMuted -// ---------------------------------------------------------------------------- -bool sound_IsMuted( ) { - return sound_muted; -} - -// ---------------------------------------------------------------------------- -// Release -// ---------------------------------------------------------------------------- -void sound_Release( ) { - sound_ReleaseBuffer(sound_buffer); - sound_ReleaseBuffer(sound_primaryBuffer); - sound_ReleaseSound( ); -} \ No newline at end of file diff --git a/core/Sound.h b/core/Sound.h index aaa3ade..10424a0 100755 --- a/core/Sound.h +++ b/core/Sound.h @@ -24,18 +24,8 @@ // ---------------------------------------------------------------------------- #ifndef SOUND_H #define SOUND_H -#define SOUND_LATENCY_NONE 0 -#define SOUND_LATENCY_VERY_LOW 1 -#define SOUND_LATENCY_LOW 2 -#define SOUND_LATENCY_MEDIUM 3 -#define SOUND_LATENCY_HIGH 4 -#define SOUND_LATENCY_VERY_HIGH 5 -//#include -#include "Common.h" -#include "Logger.h" #include "ProSystem.h" -#include "Configuration.h" #include "Tia.h" #include "Pokey.h" @@ -43,17 +33,8 @@ typedef unsigned char byte; typedef unsigned short word; typedef unsigned int uint; -extern bool sound_Initialize(HWND hWnd); -extern bool sound_Store( ); -extern bool sound_Clear( ); -extern bool sound_SetFormat(WAVEFORMATEX format); -extern bool sound_Play( ); -extern bool sound_Stop( ); -extern bool sound_SetSampleRate(uint rate); -extern uint sound_GetSampleRate( ); -extern bool sound_SetMuted(bool muted); -extern bool sound_IsMuted( ); -extern void sound_Release( ); -extern byte sound_latency; +extern uint sound_Store(byte *out_buffer); +extern void sound_SetSampleRate(uint rate); +extern uint sound_GetSampleRate(); -#endif \ No newline at end of file +#endif