Skip to content

Commit

Permalink
Back to ye olde signed 16
Browse files Browse the repository at this point in the history
  • Loading branch information
dashodanger committed Oct 19, 2024
1 parent 556e989 commit ebebbd4
Show file tree
Hide file tree
Showing 22 changed files with 174 additions and 159 deletions.
20 changes: 6 additions & 14 deletions libraries/libRAD/opal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,16 +398,14 @@ void Opal::Port(uint16_t reg_num, uint8_t val)
}

//==================================================================================================
// Generate sample. Every time you call this you will get two floating point samples (one for each
// Generate sample. Every time you call this you will get two signed 16-bit samples (one for each
// stereo channel) which will sound correct when played back at the sample rate given when the
// class was constructed.
//==================================================================================================
void Opal::Sample(float *left, float *right)
{
void Opal::Sample(int16_t *left, int16_t *right) {

// If the destination sample rate is higher than the OPL3 sample rate, we need to skip ahead
while (SampleAccum >= SampleRate)
{
while (SampleAccum >= SampleRate) {

LastOutput[0] = CurrOutput[0];
LastOutput[1] = CurrOutput[1];
Expand All @@ -419,15 +417,9 @@ void Opal::Sample(float *left, float *right)

// Mix with the partial accumulation
int32_t omblend = SampleRate - SampleAccum;
#if defined _MSC_VER || (defined __SIZEOF_FLOAT__ && __SIZEOF_FLOAT__ == 4)
*(uint32_t *)left = 0x43818000^(uint16_t)((LastOutput[0] * omblend + CurrOutput[0] * SampleAccum) / SampleRate);
*left -= 259.0f;
*(uint32_t *)right = 0x43818000^(uint16_t)((LastOutput[1] * omblend + CurrOutput[1] * SampleAccum) / SampleRate);
*right -= 259.0f;
#else
*left = (float)((LastOutput[0] * omblend + CurrOutput[0] * SampleAccum) / SampleRate) * 0.000030517578125f;
*right = (float)((LastOutput[1] * omblend + CurrOutput[1] * SampleAccum) / SampleRate) * 0.000030517578125f;
#endif
*left = (LastOutput[0] * omblend + CurrOutput[0] * SampleAccum) / SampleRate;
*right = (LastOutput[1] * omblend + CurrOutput[1] * SampleAccum) / SampleRate;

SampleAccum += OPL3SampleRate;
}

Expand Down
3 changes: 1 addition & 2 deletions libraries/libRAD/opal.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,11 @@ class Opal

void SetSampleRate(int sample_rate);
void Port(uint16_t reg_num, uint8_t val);
void Sample(float *left, float *right);
void Sample(int16_t *left, int16_t *right);

protected:
void Init(int sample_rate);
void Output(int16_t &left, int16_t &right);
inline float OutputToFloat(int16_t in);

int32_t SampleRate;
int32_t SampleAccum;
Expand Down
4 changes: 2 additions & 2 deletions libraries/libRAD/radmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ bool OPLPlayer::loadPatches()
}

// ----------------------------------------------------------------------------
void OPLPlayer::generate(float *data, unsigned numSamples)
void OPLPlayer::generate(int16_t *data, unsigned numSamples)
{
unsigned int samp = 0;

Expand Down Expand Up @@ -127,7 +127,7 @@ void OPLPlayer::runSamples(unsigned count)
// (i.e. when forcing a voice off, changing 4op flags, etc.)
while (count--)
{
std::pair<float, float> output;
std::pair<int16_t, int16_t> output;
m_opl3->Sample(&output.first, &output.second);
m_sampleFIFO.push(output);
}
Expand Down
6 changes: 3 additions & 3 deletions libraries/libRAD/radmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class OPLPlayer
// load built-in instrument patches
bool loadPatches();

void generate(float *data, unsigned numSamples);
void generate(int16_t *data, unsigned numSamples);

// reset OPL and midi file
void reset();
Expand Down Expand Up @@ -146,9 +146,9 @@ class OPLPlayer
Opal *m_opl3 = nullptr;
int rate;

std::pair<float, float> m_output; // output sample data
std::pair<int16_t, int16_t> m_output; // output sample data
// if we need to clock one of the OPLs between register writes, save the resulting sample
std::queue<std::pair<float, float>> m_sampleFIFO;
std::queue<std::pair<int16_t, int16_t>> m_sampleFIFO;

MIDIChannel m_channels[16];
std::vector<OPLVoice> m_voices;
Expand Down
8 changes: 4 additions & 4 deletions source_files/edge/i_movie.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ void MovieAudioCallback(plm_t *mpeg, plm_samples_t *samples, void *user)
{
(void)mpeg;
(void)user;
SoundData *movie_buf = SoundQueueGetFreeBuffer(PLM_AUDIO_SAMPLES_PER_FRAME);
if (movie_buf)
//SoundData *movie_buf = SoundQueueGetFreeBuffer(PLM_AUDIO_SAMPLES_PER_FRAME);
//if (movie_buf)
{
movie_buf->length_ = PLM_AUDIO_SAMPLES_PER_FRAME;
/*movie_buf->length_ = PLM_AUDIO_SAMPLES_PER_FRAME;
memcpy(movie_buf->data_, samples->interleaved, PLM_AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(float));
SoundQueueAddBuffer(movie_buf, movie_sample_rate);
SoundQueueAddBuffer(movie_buf, movie_sample_rate);*/
}
}

Expand Down
9 changes: 5 additions & 4 deletions source_files/edge/i_sound.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static bool TryOpenSound(int want_freq, bool want_stereo)
LogPrint("StartupSound: trying %d Hz %s\n", want_freq, want_stereo ? "Stereo" : "Mono");

trydev.freq = want_freq;
trydev.format = AUDIO_F32SYS;
trydev.format = AUDIO_S16SYS;
trydev.channels = want_stereo ? 2 : 1;
trydev.samples = 1024;
trydev.callback = SoundFillCallback;
Expand Down Expand Up @@ -137,7 +137,7 @@ void StartupAudio(void)
// desired format and convert silently if needed, but they might end up
// being a good safety net - Dasho

if (sound_device_check.format != AUDIO_F32SYS)
if (sound_device_check.format != AUDIO_S16SYS)
{
LogPrint("StartupSound: unsupported format: %d\n", sound_device_check.format);
SDL_CloseAudioDevice(current_sound_device);
Expand All @@ -159,12 +159,13 @@ void StartupAudio(void)
else if (!want_stereo && sound_device_check.channels != 1)
LogPrint("StartupSound: mono sound not available.\n");

if (sound_device_check.freq != want_freq)
if (sound_device_check.freq < (want_freq - want_freq / 100) ||
sound_device_check.freq > (want_freq + want_freq / 100))
{
LogPrint("StartupSound: %d Hz sound not available.\n", want_freq);
}

sound_device_bytes_per_sample = sound_device_check.channels * sizeof(float);
sound_device_bytes_per_sample = (sound_device_check.channels) * sizeof(int16_t);
sound_device_samples_per_buffer = sound_device_check.size / sound_device_bytes_per_sample;

EPI_ASSERT(sound_device_bytes_per_sample > 0);
Expand Down
70 changes: 47 additions & 23 deletions source_files/edge/s_blit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@
#include "s_music.h"
#include "s_sound.h"

// Sound must be clipped to prevent distortion (clipping is
// a kind of distortion of course, but it's much better than
// the "white noise" you get when values overflow).
//
// The more safe bits there are, the less likely the final
// output sum will overflow into white noise, but the less
// precision you have left for the volume multiplier.
static constexpr uint8_t kSafeClippingBits = 4;
static constexpr int32_t kSoundClipThreshold = ((1 << (31 - kSafeClippingBits)) - 1);

static constexpr uint8_t kMinimumSoundChannels = 32;
static constexpr uint16_t kMaximumSoundChannels = 256;

Expand All @@ -56,7 +66,7 @@ int ddf_reverb_ratio = 0;
int ddf_reverb_delay = 0;
float music_player_gain = 1.0f;

static float *mix_buffer;
static int *mix_buffer;
static int mix_buffer_length;

static constexpr uint8_t kMaximumQueueBuffers = 16;
Expand Down Expand Up @@ -135,51 +145,52 @@ void SoundChannel::ComputeVolume()
}
}

float MAX_VOL = 1.0f;
float MAX_VOL = (1 << (16 - kSafeClippingBits)) - 3;

MAX_VOL = (boss_ ? MAX_VOL : MAX_VOL / dist) * sound_effect_volume.f_;

if (definition_)
MAX_VOL *= definition_->volume_;

// strictly linear equations
volume_left_ = (MAX_VOL * (1.0 - sep));
volume_right_ = (MAX_VOL * (0.0 + sep));
volume_left_ = (int)(MAX_VOL * (1.0 - sep));
volume_right_ = (int)(MAX_VOL * (0.0 + sep));

if (var_sound_stereo == 2) /* SWAP ! */
{
if (!fliplevels.d_)
{
float tmp = volume_left_;
int tmp = volume_left_;
volume_left_ = volume_right_;
volume_right_ = tmp;
}
}
else if (fliplevels.d_)
{
float tmp = volume_left_;
int tmp = volume_left_;
volume_left_ = volume_right_;
volume_right_ = tmp;
}
}

void SoundChannel::ComputeMusicVolume()
{
float MAX_VOL = 1.0f;
float MAX_VOL = (1 << (16 - kSafeClippingBits)) - 3;

MAX_VOL = MAX_VOL * music_volume.f_ * music_player_gain; // This last one is an internal value that depends on music format
MAX_VOL = MAX_VOL * music_volume.f_ *
music_player_gain; // This last one is an internal value that depends on music format

volume_left_ = MAX_VOL;
volume_right_ = MAX_VOL;
volume_left_ = (int)MAX_VOL;
volume_right_ = (int)MAX_VOL;
}

//----------------------------------------------------------------------------

static void MixInterleaved(SoundChannel *chan, float *dest, int pairs)
static void MixInterleaved(SoundChannel *chan, int *dest, int pairs)
{
EPI_ASSERT(pairs > 0);

float *src = nullptr;
int16_t *src = nullptr;

if (paused || menu_active)
src = chan->data_->data_;
Expand All @@ -192,8 +203,8 @@ static void MixInterleaved(SoundChannel *chan, float *dest, int pairs)
src = chan->data_->filter_data_;
}

float *d_pos = dest;
float *d_end = d_pos + pairs * (sound_device_stereo ? 2 : 1);
int *d_pos = dest;
int *d_end = d_pos + pairs * (sound_device_stereo ? 2 : 1);

uint32_t offset = chan->offset_;

Expand All @@ -215,7 +226,7 @@ static void MixInterleaved(SoundChannel *chan, float *dest, int pairs)
{
uint32_t pos = (offset >> 9) & ~1;

*d_pos++ += ((src[pos] * chan->volume_left_) + (src[pos | 1] * chan->volume_right_)) * 0.5f;
*d_pos++ += ((src[pos] * chan->volume_left_) + (src[pos | 1] * chan->volume_right_)) >> 1;

offset += chan->delta_;
}
Expand All @@ -231,12 +242,12 @@ static void MixOneChannel(SoundChannel *chan, int pairs)
if (sound_effects_paused && chan->category_ >= kCategoryPlayer)
return;

if (AlmostEquals(chan->volume_left_, 0.0f) && AlmostEquals(chan->volume_right_, 0.0f))
if (chan->volume_left_ == 0 && chan->volume_right_ == 0)
return;

EPI_ASSERT(chan->offset_ < chan->length_);

float *dest = mix_buffer;
int *dest = mix_buffer;

while (pairs > 0)
{
Expand Down Expand Up @@ -307,12 +318,12 @@ static void MixQueues(int pairs)
if (!chan || !chan->data_ || chan->state_ != kChannelPlaying)
return;

if (AlmostEquals(chan->volume_left_, 0.0f) && AlmostEquals(chan->volume_right_, 0.0f))
if (chan->volume_left_ == 0 && chan->volume_right_ == 0)
return;

EPI_ASSERT(chan->offset_ < chan->length_);

float *dest = mix_buffer;
int *dest = mix_buffer;

while (pairs > 0)
{
Expand Down Expand Up @@ -373,7 +384,7 @@ void MixAllSoundChannels(void *stream, int len)
EPI_ASSERT(mix_buffer && samples <= mix_buffer_length);

// clear mixer buffer
memset(mix_buffer, 0, mix_buffer_length * sizeof(float));
memset(mix_buffer, 0, mix_buffer_length * sizeof(int));

// add each channel
for (int i = 0; i < total_channels; i++)
Expand All @@ -386,8 +397,21 @@ void MixAllSoundChannels(void *stream, int len)

MixQueues(pairs);

// copy to the SDL stream
memcpy((float *)stream, mix_buffer, samples * sizeof(float));
// blit to the SDL stream
const int *mix_ptr = mix_buffer;
const int *mix_end = mix_ptr + samples;
int16_t *dest = (int16_t *)stream;
while (mix_ptr < mix_end)
{
int val = *mix_ptr++;

if (val > kSoundClipThreshold)
val = kSoundClipThreshold;
else if (val < -kSoundClipThreshold)
val = -kSoundClipThreshold;

*dest++ = (int16_t)(val >> (16 - kSafeClippingBits));
}
}

//----------------------------------------------------------------------------
Expand All @@ -406,7 +430,7 @@ void InitializeSoundChannels(int total)

// allocate mixer buffer
mix_buffer_length = sound_device_samples_per_buffer * (sound_device_stereo ? 2 : 1);
mix_buffer = new float[mix_buffer_length];
mix_buffer = new int[mix_buffer_length];
}

void FreeSoundChannels(void)
Expand Down
4 changes: 2 additions & 2 deletions source_files/edge/s_blit.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class SoundChannel
uint32_t length_;
uint32_t delta_;

float volume_left_; // mixing volume
float volume_right_;
int volume_left_; // mixing volume
int volume_right_;

bool loop_; // will loop *one* more time
bool boss_;
Expand Down
14 changes: 6 additions & 8 deletions source_files/edge/s_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static void LoadSilence(SoundData *buf)
buf->frequency_ = sound_device_frequency;
buf->Allocate(length);

memset(buf->data_, 0, length * sizeof(float) * 2);
memset(buf->data_, 0, length * sizeof(int16_t) * 2);
}

static bool LoadDoom(SoundData *buf, const uint8_t *lump, int length)
Expand All @@ -85,16 +85,14 @@ static bool LoadDoom(SoundData *buf, const uint8_t *lump, int length)
const uint8_t *src = lump + 8;
const uint8_t *s_end = src + length;

float *dest = buf->data_;
float src_f = 0;
int16_t *dest = buf->data_;
int16_t out = 0;

for (; src < s_end; src++)
{
int16_t in = ((*src ^ 0x80) << 8);
*(uint32_t *)&src_f=0x43818000^((uint16_t)in);
src_f -= 259.0f;
*dest++ = src_f;
*dest++ = src_f;
out = (*src ^ 0x80) << 8;
*dest++ = out;
*dest++ = out;
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion source_files/edge/s_flac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ bool FLACPlayer::StreamIntoBuffer(SoundData *buf)
{
bool song_done = false;

drflac_uint64 frames = drflac_read_pcm_frames_f32(flac_track_, kMusicBuffer, buf->data_);
drflac_uint64 frames = drflac_read_pcm_frames_s16(flac_track_, kMusicBuffer, buf->data_);

if (frames < kMusicBuffer)
song_done = true;
Expand Down
Loading

0 comments on commit ebebbd4

Please sign in to comment.