Skip to content

Commit

Permalink
restore sdirectsound.cpp to upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
sh95014 committed Dec 10, 2023
1 parent fce3157 commit 89d9329
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 190 deletions.
4 changes: 2 additions & 2 deletions source/frontends/mariani/cadirectsound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ namespace
{
memset(data + dwAudioBytes1 + dwAudioBytes2, 0, size - (dwAudioBytes1 + dwAudioBytes2));
}

dsg->setVolumeIfNecessary();

return noErr;
}

Expand Down
189 changes: 1 addition & 188 deletions source/frontends/sdl/sdirectsound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
#include "SoundCore.h"
#include "Log.h"

#ifndef USE_COREAUDIO
#include <SDL.h>
#else
#include <AudioToolbox/AudioToolbox.h>
#endif // USE_COREAUDIO

#include <unordered_map>
#include <memory>
Expand All @@ -28,14 +24,6 @@ namespace
std::string audioDeviceName;
size_t audioBuffer = 0;

#ifdef USE_COREAUDIO
OSStatus DirectSoundRenderProc(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
#else
size_t getBytesPerSecond(const SDL_AudioSpec & spec)
{
const size_t bitsPerSample = spec.format & SDL_AUDIO_MASK_BITSIZE;
Expand All @@ -50,7 +38,6 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
k *= 2;
return k;
}
#endif // USE_COREAUDIO

class DirectSoundGenerator : public IDirectSoundBuffer
{
Expand All @@ -67,18 +54,7 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
void printInfo();
sa2::SoundInfo getInfo();

#ifdef USE_COREAUDIO
friend OSStatus DirectSoundRenderProc(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
void setVolumeIfNecessary();
#endif // USE_COREAUDIO

private:
#ifndef USE_COREAUDIO
static void staticAudioCallback(void* userdata, uint8_t* stream, int len);

void audioCallback(uint8_t* stream, int len);
Expand All @@ -87,23 +63,14 @@ OSStatus DirectSoundRenderProc(void * inRefCon,

SDL_AudioDeviceID myAudioDevice;
SDL_AudioSpec myAudioSpec;
#else
std::vector<uint8_t> myMixerBuffer;

AudioUnit outputUnit;
Float32 volume;
#endif // USE_COREAUDIO

size_t myBytesPerSecond;

#ifndef USE_COREAUDIO
uint8_t * mixBufferTo(uint8_t * stream);
#endif
};

std::unordered_map<DirectSoundGenerator *, std::shared_ptr<DirectSoundGenerator> > activeSoundGenerators;

#ifndef USE_COREAUDIO
void DirectSoundGenerator::staticAudioCallback(void* userdata, uint8_t* stream, int len)
{
DirectSoundGenerator * generator = static_cast<DirectSoundGenerator *>(userdata);
Expand Down Expand Up @@ -138,19 +105,12 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
memset(stream, myAudioSpec.silence, gap);
}
}
#endif // USE_COREAUDIO

DirectSoundGenerator::DirectSoundGenerator(LPCDSBUFFERDESC lpcDSBufferDesc, const char * deviceName, const size_t ms)
: IDirectSoundBuffer(lpcDSBufferDesc)
#ifndef USE_COREAUDIO
, myAudioDevice(0)
#else
, outputUnit(0)
, volume(0)
#endif
, myBytesPerSecond(0)
{
#ifndef USE_COREAUDIO
SDL_zero(myAudioSpec);

SDL_AudioSpec want;
Expand All @@ -174,121 +134,42 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
{
throw std::runtime_error(sa2::decorateSDLError("SDL_OpenAudioDevice"));
}
#else
AudioComponentDescription desc = { 0 };
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;

AudioComponent comp = AudioComponentFindNext(NULL, &desc);
if (comp == NULL)
{
fprintf(stderr, "can't find audio component\n");
return;
}

if (AudioComponentInstanceNew(comp, &outputUnit) != noErr)
{
fprintf(stderr, "can't create output unit\n");
return;
}

AudioStreamBasicDescription absd = { 0 };
absd.mSampleRate = mySampleRate;
absd.mFormatID = kAudioFormatLinearPCM;
absd.mFormatFlags = kAudioFormatFlagIsSignedInteger;
absd.mFramesPerPacket = 1;
absd.mChannelsPerFrame = (UInt32)myChannels;
absd.mBitsPerChannel = sizeof(SInt16) * CHAR_BIT;
absd.mBytesPerPacket = sizeof(SInt16) * (UInt32)myChannels;
absd.mBytesPerFrame = sizeof(SInt16) * (UInt32)myChannels;
if (AudioUnitSetProperty(outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&absd,
sizeof(absd))) {
fprintf(stderr, "can't set stream format\n");
return;
}

AURenderCallbackStruct input;
input.inputProc = DirectSoundRenderProc;
input.inputProcRefCon = this;
if (AudioUnitSetProperty(outputUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&input,
sizeof(input)) != noErr)
{
fprintf(stderr, "can't set callback property\n");
return;
}

setVolumeIfNecessary();

if (AudioUnitInitialize(outputUnit) != noErr)
{
fprintf(stderr, "can't initialize output unit\n");
return;
}

OSStatus status = AudioOutputUnitStart(outputUnit);
fprintf(stderr, "output unit %p, status %d\n", outputUnit, status);
#endif
}

DirectSoundGenerator::~DirectSoundGenerator()
{
#ifndef USE_COREAUDIO
SDL_PauseAudioDevice(myAudioDevice, 1);
SDL_CloseAudioDevice(myAudioDevice);
#endif // USE_COREAUDIO
}

HRESULT DirectSoundGenerator::Release()
{
#ifndef USE_COREAUDIO
activeSoundGenerators.erase(this); // this will force the destructor
return IUnknown::Release();
#else
AudioOutputUnitStop(outputUnit);
AudioUnitUninitialize(outputUnit);
AudioComponentInstanceDispose(outputUnit);
outputUnit = 0;
return S_OK;
#endif // USE_COREAUDIO
}

HRESULT DirectSoundGenerator::Stop()
{
const HRESULT res = IDirectSoundBuffer::Stop();
#ifndef USE_COREAUDIO
SDL_PauseAudioDevice(myAudioDevice, 1);
#endif // USE_COREAUDIO
return res;
}

HRESULT DirectSoundGenerator::Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags )
{
const HRESULT res = IDirectSoundBuffer::Play(dwReserved1, dwReserved2, dwFlags);
#ifndef USE_COREAUDIO
SDL_PauseAudioDevice(myAudioDevice, 0);
#endif // USE_COREAUDIO
return res;
}

void DirectSoundGenerator::printInfo()
{
#ifndef USE_COREAUDIO
const DWORD bytesInBuffer = GetBytesInBuffer();
std::cerr << "Channels: " << (int)myAudioSpec.channels;
std::cerr << ", buffer: " << std::setw(6) << bytesInBuffer;
const double time = double(bytesInBuffer) / myBytesPerSecond * 1000;
std::cerr << ", " << std::setw(8) << time << " ms";
std::cerr << ", underruns: " << std::setw(10) << GetBufferUnderruns() << std::endl;
#endif // USE_COREAUDIO
}

sa2::SoundInfo DirectSoundGenerator::getInfo()
Expand All @@ -298,7 +179,7 @@ OSStatus DirectSoundRenderProc(void * inRefCon,

sa2::SoundInfo info;
info.running = dwStatus & DSBSTATUS_PLAYING;
info.channels = (UInt32)myChannels;
info.channels = myChannels;
info.volume = GetLogarithmicVolume();
info.numberOfUnderruns = GetBufferUnderruns();

Expand All @@ -318,7 +199,6 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
ResetUnderrruns();
}

#ifndef USE_COREAUDIO
uint8_t * DirectSoundGenerator::mixBufferTo(uint8_t * stream)
{
// we could copy ADJUST_VOLUME from SDL_mixer.c and avoid all copying and (rare) race conditions
Expand All @@ -332,74 +212,7 @@ OSStatus DirectSoundRenderProc(void * inRefCon,
SDL_MixAudioFormat(stream, myMixerBuffer.data(), myAudioSpec.format, len, svolume);
return stream + len;
}
#endif // USE_COREAUDIO

#ifdef USE_COREAUDIO
void DirectSoundGenerator::setVolumeIfNecessary()
{
const double logVolume = GetLogarithmicVolume();
// same formula as QAudio::convertVolume()
const Float32 linVolume = logVolume > 0.99 ? 1.0 : -std::log(1.0 - logVolume) / std::log(100.0);
if (fabs(linVolume - volume) > FLT_EPSILON) {
if (AudioUnitSetParameter(outputUnit,
kHALOutputParam_Volume,
kAudioUnitScope_Global,
0,
linVolume,
0) == noErr)
{
volume = linVolume;
}
else
{
fprintf(stderr, "can't set volume\n");
}
}
}

OSStatus DirectSoundRenderProc(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
DirectSoundGenerator *dsg = (DirectSoundGenerator *)inRefCon;
UInt8 * data = (UInt8 *)ioData->mBuffers[0].mData;

DWORD size = (DWORD)(inNumberFrames * dsg->myChannels * sizeof(SInt16));

LPVOID lpvAudioPtr1, lpvAudioPtr2;
DWORD dwAudioBytes1, dwAudioBytes2;
dsg->Read(size,
&lpvAudioPtr1,
&dwAudioBytes1,
&lpvAudioPtr2,
&dwAudioBytes2);

// copy the first part from the ring buffer
if (lpvAudioPtr1 && dwAudioBytes1)
{
memcpy(data, lpvAudioPtr1, dwAudioBytes1);
}
// copy the second (wrapped-around) part of the ring buffer, if any
if (lpvAudioPtr2 && dwAudioBytes2)
{
memcpy(data + dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
}
// doesn't seem ever necessary, but fill the rest of the requested buffer with silence
// if DirectSoundGenerator doesn't have enough
if (size > dwAudioBytes1 + dwAudioBytes2)
{
memset(data + dwAudioBytes1 + dwAudioBytes2, 0, size - (dwAudioBytes1 + dwAudioBytes2));
}

dsg->setVolumeIfNecessary();

return noErr;
}
#endif // USE_COREAUDIO

}

IDirectSoundBuffer * iCreateDirectSoundBuffer(LPCDSBUFFERDESC lpcDSBufferDesc)
Expand Down

0 comments on commit 89d9329

Please sign in to comment.