PC audio now supports volume and stereo channels.

This commit is contained in:
Scott Duensing 2022-09-14 19:14:30 -05:00
parent ce2d13ba0d
commit 2ca7c683dd
4 changed files with 101 additions and 12 deletions

View file

@ -32,7 +32,7 @@
#include "jPixBuf.h"
#define AUDIO_FORMAT AUDIO_F32
#define AUDIO_FORMAT AUDIO_F32 // PocketMod returns floats.
#define AUDIO_FREQUENCY 44100
#define AUDIO_CHANNELS 2
@ -73,6 +73,7 @@ static SDL_AudioSpec _jlAudioFormat;
static SDL_AudioDeviceID _jlAudioDevice;
static jbool _jlModPlaying = jfalse;
static jlPlatformModT *_jlModCurrent = NULL;
static jbyte _jlModVolume = 255;
static jlSoundPlayingT *_jlSoundList = NULL;
@ -80,6 +81,9 @@ static Uint32 _jlUtilTimer(Uint32 interval, void *param);
static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes);
extern jbool _jlSwapChannels;
/*
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@ -154,11 +158,21 @@ void _jlPutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {
static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes) {
int i = 0;
jlSoundPlayingT *sound = NULL;
jlSoundPlayingT *prev = NULL;
jlSoundPlayingT *temp = NULL;
uint32_t length;
int i = 0;
jlSoundPlayingT *sound = NULL;
jlSoundPlayingT *prev = NULL;
jlSoundPlayingT *temp = NULL;
uint32_t length = 0;
float *data = NULL;
float *out = NULL;
float adjust = 1;
double work = 0;
uint8_t *mix = NULL;
jbool isRight = jfalse;
static uint8_t *samples = NULL;
static uint32_t sampleBufferSize = 0;
(void)userdata;
// Silence buffer.
memset(buffer, 0, bytes);
@ -166,8 +180,25 @@ static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes) {
// Load in music.
if (_jlModPlaying) {
while (i < bytes) {
//***TODO*** No MOD volume control.
i += pocketmod_render(userdata, buffer + i, bytes - i);
i += pocketmod_render(&_jlModContext, buffer + i, bytes - i);
}
// Adjust volume.
adjust = ((100.0 / 255.0) * (float)_jlModVolume) * 0.01;
data = (float *)buffer;
for (i=0; i<(int)(bytes / sizeof(float)); i+=2) {
data[i] *= adjust;
data[i + 1] *= adjust;
}
}
// Create a sample buffer for manipulating sound effects.
if (sampleBufferSize < (uint32_t)bytes) {
if (samples) jlFree(samples);
samples = jlMalloc(bytes);
if (samples) {
sampleBufferSize = bytes;
} else {
sampleBufferSize = 0;
}
}
@ -175,8 +206,32 @@ static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes) {
if (_jlSoundList) {
sound = _jlSoundList;
while (sound) {
length = ((uint32_t)bytes > sound->len) ? sound->len : bytes;
SDL_MixAudioFormat(buffer, sound->buffer, AUDIO_FORMAT, length, sound->volume * 0.5);
length = ((uint32_t)bytes > sound->len) ? sound->len : (uint32_t)bytes;
// If we have a sample buffer, move sound to desired channel.
if (samples) {
mix = samples;
out = (float *)samples;
data = (float *)sound->buffer;
for (i=0; i<(int)(length / sizeof(float)); i+=2) {
// Combine channels into a mono sample.
work = (data[i] + data[i + 1]) * 0.5;
// Determine channel.
isRight = (sound->channel & 0x01);
if (_jlSwapChannels) isRight = !isRight;
if (isRight) {
// Move sound into right channel.
out[i] = 0;
out[i + 1] = work;
} else {
// Move sound into left channel.
out[i] = work;
out[i + 1] = 0;
}
}
} else {
mix = sound->buffer;
}
SDL_MixAudioFormat(buffer, mix, AUDIO_FORMAT, length, sound->volume * 0.5);
sound->buffer += length;
sound->len -= length;
// Are we done with this sound?
@ -391,6 +446,11 @@ void jlModStop(void) {
}
void jlModVolume(jbyte volume) {
_jlModVolume = volume;
}
void jlSoundFree(jlSoundT *sound) {
jlPlatformSoundT *s = (jlPlatformSoundT *)sound;
@ -662,7 +722,7 @@ int main(int argc, char *argv[]) {
_jlAudioFormat.channels = 2;
_jlAudioFormat.samples = AUDIO_CHANNELS;
_jlAudioFormat.callback = _jlAudioCallback;
_jlAudioFormat.userdata = &_jlModContext;
_jlAudioFormat.userdata = NULL;
_jlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &_jlAudioFormat, &_jlAudioFormat, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
if (!_jlAudioDevice) jlUtilDie(SDL_GetError());
SDL_PauseAudioDevice(_jlAudioDevice, 0);

View file

@ -74,6 +74,10 @@ jmp_buf _jlJumpBuffer;
jbool _jlIsRunning = jtrue;
#endif
#ifndef JL_HAS_SOUNDSWAPCHANNELS
jbool _jlSwapChannels = jfalse;
#endif
static jlColorT _jlDefaultPalette[16];
static jlStackT *_jlFillStackTop = NULL;
@ -797,6 +801,13 @@ void jlModStop(void) {
#endif
#ifndef JL_HAS_MODVOLUME
void jlModVolume(jbyte volume) {
(void)volume;
}
#endif
#ifndef JL_HAS_PALETTEDEFAULT
void jlPaletteDefault(void) {
jbyte i;
@ -882,6 +893,13 @@ void jlSoundStop(jlSoundT *sound) {
#endif
#ifndef JL_HAS_SOUNDSWAPCHANNELS
void jlSoundSwapChannels(jbool swap) {
_jlSwapChannels = swap;
}
#endif
#ifndef JL_HAS_STNFREE
void jlStnFree(jlStnT *stn) {
if (stn != NULL) {

View file

@ -98,6 +98,7 @@ typedef unsigned int juint32;
#define JL_HAS_MODPAUSE
#define JL_HAS_MODPLAY
#define JL_HAS_MODSTOP
#define JL_HAS_MODVOLUME
#define JL_HAS_PALETTESET
#define JL_HAS_PALETTESETFROMIMG
#define JL_HAS_SOUNDFREE
@ -142,6 +143,7 @@ typedef unsigned int juint32;
#define JL_HAS_MODPAUSE
#define JL_HAS_MODPLAY
#define JL_HAS_MODSTOP
#define JL_HAS_MODVOLUME
#define JL_HAS_PALETTESET
#define JL_HAS_PALETTESETFROMIMG
#define JL_HAS_SOUNDFREE
@ -186,6 +188,7 @@ typedef unsigned int juint32;
#define JL_HAS_MODPAUSE
#define JL_HAS_MODPLAY
#define JL_HAS_MODSTOP
#define JL_HAS_MODVOLUME
#define JL_HAS_PALETTESET
#define JL_HAS_PALETTESETFROMIMG
#define JL_HAS_SOUNDFREE
@ -440,6 +443,7 @@ jbool _jlModLoad(jlModT **mod, char *filename);
void jlModPause(void);
void jlModPlay(jlModT *mod);
void jlModStop(void);
void jlModVolume(jbyte volume);
void jlPaletteDefault(void); //***TODO*** Treat palettes like we do "surfaces" - allow changing STAs or display
void jlPaletteSet(jbyte index, jbyte r, jbyte g, jbyte b); //***TODO*** Really need a matching "get"
@ -451,6 +455,7 @@ jbool jlSoundIsPlaying(jlSoundT *sound);
jbool _jlSoundLoad(jlSoundT **sound, char *filename);
void jlSoundPlay(jlSoundT *sound, jlSoundChannelE channel, jbyte volume);
void jlSoundStop(jlSoundT *sound);
void jlSoundSwapChannels(jbool swap);
void jlStnFree(jlStnT *stn);
#define jlStnLoad(stn, filename) _jlStnLoad((jlStnT **)&(stn), filename, __LINE__, (char *)__FILE__) // Syntatic Sugar

View file

@ -290,6 +290,7 @@ void musicTest(void) {
jlModT *music = NULL;
jlSoundT *sound1 = NULL;
jlSoundT *sound2 = NULL;
jbyte volume = 0;
if (!jlImgLoad(kanga, "kanga")) jlUtilDie("Unable to load kanga.img!");
if (!jlImgLoad(font, "font")) jlUtilDie("Unable to load font.img!");
@ -302,12 +303,17 @@ void musicTest(void) {
jlModPlay(music);
jlSoundPlay(sound2, CHANNEL_FRONT_RIGHT, 255);
//jlSoundSwapChannels(jtrue);
jlSoundPlay(sound1, CHANNEL_FRONT_LEFT, 255);
jlSoundPlay(sound2, CHANNEL_FRONT_RIGHT, 255);
while (!jlKeyPressed()) {
fontPrint(font, NULL, 1, 1, "%dx%d %d %d ", jlGameGetAxis(0), jlGameGetAxis(1), jlGameGetButton(0), jlGameGetButton(1));
jlDisplayPresent();
if (volume < 255) {
volume++;
jlModVolume(volume);
}
}
jlKeyRead();