diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 17f6d242e..a05b12fc6 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -176,10 +176,15 @@ static TArray customStreams; SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, MusicCustomStreamType sampletype, StreamCallback cb, void *userdata) { - int flags = 0; - if (numchannels < 2) flags |= SoundStream::Mono; - if (sampletype == MusicSamplesFloat) flags |= SoundStream::Float; - auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata); + ChannelConfig chans; + if(numchannels == 1) + chans = ChannelConfig_Mono; + else if(numchannels == 2) + chans = ChannelConfig_Stereo; + else + return nullptr; + + auto stream = GSnd->CreateStream(cb, int(size), SampleType_Int16, chans, samplerate, userdata); if (stream) { stream->Play(true, 1); @@ -251,17 +256,14 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) void S_CreateStream() { if (!mus_playing.handle) return; - SoundStreamInfo fmt; - ZMusic_GetStreamInfo(mus_playing.handle, &fmt); - // always create a floating point streaming buffer so we can apply replay gain without risk of integer overflows. - mus_playing.isfloat = fmt.mNumChannels > 0; + SoundStreamInfoEx fmt; + ZMusic_GetStreamInfoEx(mus_playing.handle, &fmt); + mus_playing.isfloat = fmt.mSampleType == SampleType_Float32; if (!mus_playing.isfloat) fmt.mBufferSize *= 2; if (fmt.mBufferSize > 0) // if buffer size is 0 the library will play the song itself (e.g. Windows system synth.) { - int flags = SoundStream::Float; - if (abs(fmt.mNumChannels) < 2) flags |= SoundStream::Mono; - - musicStream.reset(GSnd->CreateStream(FillStream, fmt.mBufferSize, flags, fmt.mSampleRate, nullptr)); + // always create a floating point streaming buffer so we can apply replay gain without risk of integer overflows. + musicStream.reset(GSnd->CreateStream(FillStream, fmt.mBufferSize, SampleType_Float32, fmt.mChannelConfig, fmt.mSampleRate, nullptr)); if (musicStream) musicStream->Play(true, 1); } } @@ -603,17 +605,14 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const return; // unable to open } - SoundStreamInfo fmt; - ZMusic_GetStreamInfo(handle, &fmt); + SoundStreamInfoEx fmt; + ZMusic_GetStreamInfoEx(handle, &fmt); if (fmt.mBufferSize == 0) { ZMusic_Close(handle); return; // external player. } - int flags = SoundStream::Float; - if (abs(fmt.mNumChannels) < 2) flags |= SoundStream::Mono; - TArray readbuffer(fmt.mBufferSize, true); TArray lbuffer; TArray rbuffer; @@ -621,7 +620,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const { unsigned index; // 4 cases, all with different preparation needs. - if (fmt.mNumChannels == -2) // 16 bit stereo + if (fmt.mSampleType == SampleType_Int16 && fmt.mChannelConfig == ChannelConfig_Stereo) // 16 bit stereo { int16_t* sbuf = (int16_t*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 4; @@ -634,7 +633,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const rbuffer[index + i] = sbuf[i * 2 + 1]; } } - else if (fmt.mNumChannels == -1) // 16 bit mono + else if (fmt.mSampleType == SampleType_Int16 && fmt.mChannelConfig == ChannelConfig_Mono) // 16 bit mono { int16_t* sbuf = (int16_t*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 2; @@ -645,7 +644,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const lbuffer[index + i] = sbuf[i]; } } - else if (fmt.mNumChannels == 1) // float mono + else if (fmt.mSampleType == SampleType_Float32 && fmt.mChannelConfig == ChannelConfig_Mono) // float mono { float* sbuf = (float*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 4; @@ -655,7 +654,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const lbuffer[index + i] = sbuf[i] * 32768.f; } } - else if (fmt.mNumChannels == 2) // float stereo + else if (fmt.mSampleType == SampleType_Float32 && fmt.mChannelConfig == ChannelConfig_Stereo) // float stereo { float* sbuf = (float*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 8; diff --git a/src/common/audio/sound/i_sound.cpp b/src/common/audio/sound/i_sound.cpp index dda757e8d..3fe175751 100644 --- a/src/common/audio/sound/i_sound.cpp +++ b/src/common/audio/sound/i_sound.cpp @@ -169,7 +169,7 @@ public: } // Streaming sounds. - SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) + SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, SampleType stype, ChannelConfig chans, int samplerate, void *userdata) { return NULL; } @@ -299,7 +299,8 @@ const char *GetSampleTypeName(SampleType type) { case SampleType_UInt8: return "Unsigned 8-bit"; case SampleType_Int16: return "Signed 16-bit"; - default: break; + case SampleType_Float32: return "32-bit float"; + default: break; } return "(invalid sample type)"; } diff --git a/src/common/audio/sound/i_sound.h b/src/common/audio/sound/i_sound.h index e8e5a1a0e..7d0b7cb60 100644 --- a/src/common/audio/sound/i_sound.h +++ b/src/common/audio/sound/i_sound.h @@ -65,17 +65,6 @@ class SoundStream public: virtual ~SoundStream() = default; - enum - { // For CreateStream - Mono = 1, - Bits8 = 2, - Bits32 = 4, - Float = 8, - - // For OpenStream - Loop = 16 - }; - struct Position { uint64_t samplesplayed; std::chrono::nanoseconds latency; @@ -114,7 +103,7 @@ public: virtual float GetOutputRate() = 0; // Streaming sounds. - virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; + virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, SampleType stype, ChannelConfig chans, int samplerate, void *userdata) = 0; // Starts a sound. virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index 8b20fb9c1..6fcc97ea0 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -117,6 +117,27 @@ EXTERN_CVAR (Int, snd_hrtf) #define GET_PTRID(x) ((uint32_t)(uintptr_t)(x)) +static constexpr uint8_t SampleTypeSize(SampleType stype) +{ + switch(stype) + { + case SampleType_UInt8: return sizeof(uint8_t); + case SampleType_Int16: return sizeof(int16_t); + case SampleType_Float32: return sizeof(float); + } + return 0; +} + +static constexpr uint8_t ChannelCount(ChannelConfig chans) +{ + switch(chans) + { + case ChannelConfig_Mono: return 1; + case ChannelConfig_Stereo: return 2; + } + return 0; +} + static ALenum checkALError(const char *fn, unsigned int ln) { ALenum err = alGetError(); @@ -461,7 +482,7 @@ public: return ok; } - bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) + bool Init(SoundStreamCallback callback, int buffbytes, SampleType stype, ChannelConfig chans, int samplerate, void *userdata) { if(!SetupSource()) return false; @@ -471,46 +492,30 @@ public: SampleRate = samplerate; Format = AL_NONE; - if((flags&Bits8)) /* Signed or unsigned? We assume unsigned 8-bit... */ + if(stype == SampleType_UInt8) { - if((flags&Mono)) Format = AL_FORMAT_MONO8; - else Format = AL_FORMAT_STEREO8; + if(chans == ChannelConfig_Mono) Format = AL_FORMAT_MONO8; + else if(chans == ChannelConfig_Stereo) Format = AL_FORMAT_STEREO8; + } + else if(stype == SampleType_Int16) + { + if(chans == ChannelConfig_Mono) Format = AL_FORMAT_MONO16; + else if(chans == ChannelConfig_Stereo) Format = AL_FORMAT_STEREO16; } - else if((flags&Float)) + else if(stype == SampleType_Float32 && alIsExtensionPresent("AL_EXT_FLOAT32")) { - if(alIsExtensionPresent("AL_EXT_FLOAT32")) - { - if((flags&Mono)) Format = AL_FORMAT_MONO_FLOAT32; - else Format = AL_FORMAT_STEREO_FLOAT32; - } - } - else if((flags&Bits32)) - { - } - else - { - if((flags&Mono)) Format = AL_FORMAT_MONO16; - else Format = AL_FORMAT_STEREO16; + if(chans == ChannelConfig_Mono) Format = AL_FORMAT_MONO_FLOAT32; + else if(chans == ChannelConfig_Stereo) Format = AL_FORMAT_STEREO_FLOAT32; } if(Format == AL_NONE) { - Printf("Unsupported format: 0x%x\n", flags); + Printf("Unhandled audio format: %s, %s\n", GetChannelConfigName(chans), + GetSampleTypeName(stype)); return false; } - FrameSize = 1; - if((flags&Bits8)) - FrameSize *= 1; - else if((flags&(Bits32|Float))) - FrameSize *= 4; - else - FrameSize *= 2; - - if((flags&Mono)) - FrameSize *= 1; - else - FrameSize *= 2; + FrameSize = SampleTypeSize(stype) * ChannelCount(chans); buffbytes += FrameSize-1; buffbytes -= buffbytes%FrameSize; @@ -1223,12 +1228,12 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) } -SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) +SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, SampleType stype, ChannelConfig chans, int samplerate, void *userdata) { if(StreamThread.get_id() == std::thread::id()) StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); OpenALSoundStream *stream = new OpenALSoundStream(this); - if (!stream->Init(callback, buffbytes, flags, samplerate, userdata)) + if (!stream->Init(callback, buffbytes, stype, chans, samplerate, userdata)) { delete stream; return NULL; diff --git a/src/common/audio/sound/oalsound.h b/src/common/audio/sound/oalsound.h index 6e5c93a87..4055c132b 100644 --- a/src/common/audio/sound/oalsound.h +++ b/src/common/audio/sound/oalsound.h @@ -42,7 +42,7 @@ public: virtual float GetOutputRate(); // Streaming sounds. - virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata); + SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, SampleType stype, ChannelConfig chans, int samplerate, void *userdata) override; // Starts a sound. FISoundChannel *StartSound(SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) override;