mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-04-19 17:01:46 +00:00
Merge ffab3a1b46
into 6481f8cce9
This commit is contained in:
commit
c21b406849
5 changed files with 79 additions and 100 deletions
|
@ -173,10 +173,16 @@ static TArray<SoundStream*> 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;
|
||||
const SampleType stype{(sampletype == MusicSamplesFloat) ? SampleType_Float32 : SampleType_Int16};
|
||||
|
||||
auto stream = GSnd->CreateStream(cb, int(size), stype, chans, samplerate, userdata);
|
||||
if (stream)
|
||||
{
|
||||
stream->Play(true, 1);
|
||||
|
@ -248,17 +254,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);
|
||||
}
|
||||
}
|
||||
|
@ -599,17 +602,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<uint8_t> readbuffer(fmt.mBufferSize, true);
|
||||
TArray<float> lbuffer;
|
||||
TArray<float> rbuffer;
|
||||
|
@ -617,7 +617,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;
|
||||
|
@ -630,7 +630,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;
|
||||
|
@ -641,7 +641,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;
|
||||
|
@ -651,7 +651,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;
|
||||
|
|
|
@ -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)";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -117,6 +117,47 @@ 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 constexpr ALenum GetFormat(SampleType stype, ChannelConfig chans)
|
||||
{
|
||||
if(stype == SampleType_UInt8)
|
||||
{
|
||||
if(chans == ChannelConfig_Mono) return AL_FORMAT_MONO8;
|
||||
if(chans == ChannelConfig_Stereo) return AL_FORMAT_STEREO8;
|
||||
}
|
||||
if(stype == SampleType_Int16)
|
||||
{
|
||||
if(chans == ChannelConfig_Mono) return AL_FORMAT_MONO16;
|
||||
if(chans == ChannelConfig_Stereo) return AL_FORMAT_STEREO16;
|
||||
}
|
||||
if(stype == SampleType_Float32)
|
||||
{
|
||||
if(chans == ChannelConfig_Mono) return AL_FORMAT_MONO_FLOAT32;
|
||||
if(chans == ChannelConfig_Stereo) return AL_FORMAT_STEREO_FLOAT32;
|
||||
}
|
||||
return AL_NONE;
|
||||
}
|
||||
|
||||
static ALenum checkALError(const char *fn, unsigned int ln)
|
||||
{
|
||||
ALenum err = alGetError();
|
||||
|
@ -461,7 +502,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;
|
||||
|
@ -470,47 +511,15 @@ public:
|
|||
UserData = userdata;
|
||||
SampleRate = samplerate;
|
||||
|
||||
Format = AL_NONE;
|
||||
if((flags&Bits8)) /* Signed or unsigned? We assume unsigned 8-bit... */
|
||||
{
|
||||
if((flags&Mono)) Format = AL_FORMAT_MONO8;
|
||||
else Format = AL_FORMAT_STEREO8;
|
||||
}
|
||||
else if((flags&Float))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Format = GetFormat(stype, chans);
|
||||
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;
|
||||
|
@ -526,16 +535,6 @@ public:
|
|||
|
||||
#define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */
|
||||
|
||||
static size_t GetChannelCount(ChannelConfig chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
case ChannelConfig_Mono: return 1;
|
||||
case ChannelConfig_Stereo: return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float GetRolloff(const FRolloffInfo *rolloff, float distance)
|
||||
{
|
||||
return soundEngine->GetRolloff(rolloff, distance);
|
||||
|
@ -1105,10 +1104,6 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(uint8_t *sfxdata, int length, int
|
|||
SoundHandle OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length, int def_loop_start, int def_loop_end)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
ALenum format = AL_NONE;
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
uint32_t loop_start = 0, loop_end = ~0u;
|
||||
zmusic_bool startass = false, endass = false;
|
||||
|
||||
|
@ -1126,19 +1121,12 @@ SoundHandle OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length, int def
|
|||
if (!decoder)
|
||||
return retval;
|
||||
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
SoundDecoder_GetInfo(decoder, &srate, &chans, &type);
|
||||
int samplesize = 1;
|
||||
if (chans == ChannelConfig_Mono)
|
||||
{
|
||||
if (type == SampleType_UInt8) format = AL_FORMAT_MONO8, samplesize = 1;
|
||||
if (type == SampleType_Int16) format = AL_FORMAT_MONO16, samplesize = 2;
|
||||
}
|
||||
else if (chans == ChannelConfig_Stereo)
|
||||
{
|
||||
if (type == SampleType_UInt8) format = AL_FORMAT_STEREO8, samplesize = 2;
|
||||
if (type == SampleType_Int16) format = AL_FORMAT_STEREO16, samplesize = 4;
|
||||
}
|
||||
|
||||
ALenum format = GetFormat(type, chans);
|
||||
if (format == AL_NONE)
|
||||
{
|
||||
SoundDecoder_Close(decoder);
|
||||
|
@ -1146,6 +1134,7 @@ SoundHandle OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length, int def
|
|||
GetSampleTypeName(type));
|
||||
return retval;
|
||||
}
|
||||
int samplesize = SampleTypeSize(type) * ChannelCount(chans);
|
||||
|
||||
TArray<uint8_t> data;
|
||||
unsigned total = 0;
|
||||
|
@ -1223,12 +1212,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue