PC audio now supports volume and stereo channels.
This commit is contained in:
parent
ce2d13ba0d
commit
2ca7c683dd
4 changed files with 101 additions and 12 deletions
|
@ -32,7 +32,7 @@
|
||||||
#include "jPixBuf.h"
|
#include "jPixBuf.h"
|
||||||
|
|
||||||
|
|
||||||
#define AUDIO_FORMAT AUDIO_F32
|
#define AUDIO_FORMAT AUDIO_F32 // PocketMod returns floats.
|
||||||
#define AUDIO_FREQUENCY 44100
|
#define AUDIO_FREQUENCY 44100
|
||||||
#define AUDIO_CHANNELS 2
|
#define AUDIO_CHANNELS 2
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ static SDL_AudioSpec _jlAudioFormat;
|
||||||
static SDL_AudioDeviceID _jlAudioDevice;
|
static SDL_AudioDeviceID _jlAudioDevice;
|
||||||
static jbool _jlModPlaying = jfalse;
|
static jbool _jlModPlaying = jfalse;
|
||||||
static jlPlatformModT *_jlModCurrent = NULL;
|
static jlPlatformModT *_jlModCurrent = NULL;
|
||||||
|
static jbyte _jlModVolume = 255;
|
||||||
static jlSoundPlayingT *_jlSoundList = NULL;
|
static jlSoundPlayingT *_jlSoundList = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +81,9 @@ static Uint32 _jlUtilTimer(Uint32 interval, void *param);
|
||||||
static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes);
|
static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes);
|
||||||
|
|
||||||
|
|
||||||
|
extern jbool _jlSwapChannels;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
#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) {
|
static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
jlSoundPlayingT *sound = NULL;
|
jlSoundPlayingT *sound = NULL;
|
||||||
jlSoundPlayingT *prev = NULL;
|
jlSoundPlayingT *prev = NULL;
|
||||||
jlSoundPlayingT *temp = NULL;
|
jlSoundPlayingT *temp = NULL;
|
||||||
uint32_t length;
|
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.
|
// Silence buffer.
|
||||||
memset(buffer, 0, bytes);
|
memset(buffer, 0, bytes);
|
||||||
|
@ -166,8 +180,25 @@ static void _jlAudioCallback(void *userdata, Uint8 *buffer, int bytes) {
|
||||||
// Load in music.
|
// Load in music.
|
||||||
if (_jlModPlaying) {
|
if (_jlModPlaying) {
|
||||||
while (i < bytes) {
|
while (i < bytes) {
|
||||||
//***TODO*** No MOD volume control.
|
i += pocketmod_render(&_jlModContext, buffer + i, bytes - i);
|
||||||
i += pocketmod_render(userdata, 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) {
|
if (_jlSoundList) {
|
||||||
sound = _jlSoundList;
|
sound = _jlSoundList;
|
||||||
while (sound) {
|
while (sound) {
|
||||||
length = ((uint32_t)bytes > sound->len) ? sound->len : bytes;
|
length = ((uint32_t)bytes > sound->len) ? sound->len : (uint32_t)bytes;
|
||||||
SDL_MixAudioFormat(buffer, sound->buffer, AUDIO_FORMAT, length, sound->volume * 0.5);
|
// 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->buffer += length;
|
||||||
sound->len -= length;
|
sound->len -= length;
|
||||||
// Are we done with this sound?
|
// Are we done with this sound?
|
||||||
|
@ -391,6 +446,11 @@ void jlModStop(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void jlModVolume(jbyte volume) {
|
||||||
|
_jlModVolume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void jlSoundFree(jlSoundT *sound) {
|
void jlSoundFree(jlSoundT *sound) {
|
||||||
jlPlatformSoundT *s = (jlPlatformSoundT *)sound;
|
jlPlatformSoundT *s = (jlPlatformSoundT *)sound;
|
||||||
|
|
||||||
|
@ -662,7 +722,7 @@ int main(int argc, char *argv[]) {
|
||||||
_jlAudioFormat.channels = 2;
|
_jlAudioFormat.channels = 2;
|
||||||
_jlAudioFormat.samples = AUDIO_CHANNELS;
|
_jlAudioFormat.samples = AUDIO_CHANNELS;
|
||||||
_jlAudioFormat.callback = _jlAudioCallback;
|
_jlAudioFormat.callback = _jlAudioCallback;
|
||||||
_jlAudioFormat.userdata = &_jlModContext;
|
_jlAudioFormat.userdata = NULL;
|
||||||
_jlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &_jlAudioFormat, &_jlAudioFormat, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
_jlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &_jlAudioFormat, &_jlAudioFormat, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||||
if (!_jlAudioDevice) jlUtilDie(SDL_GetError());
|
if (!_jlAudioDevice) jlUtilDie(SDL_GetError());
|
||||||
SDL_PauseAudioDevice(_jlAudioDevice, 0);
|
SDL_PauseAudioDevice(_jlAudioDevice, 0);
|
||||||
|
|
|
@ -74,6 +74,10 @@ jmp_buf _jlJumpBuffer;
|
||||||
jbool _jlIsRunning = jtrue;
|
jbool _jlIsRunning = jtrue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef JL_HAS_SOUNDSWAPCHANNELS
|
||||||
|
jbool _jlSwapChannels = jfalse;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static jlColorT _jlDefaultPalette[16];
|
static jlColorT _jlDefaultPalette[16];
|
||||||
static jlStackT *_jlFillStackTop = NULL;
|
static jlStackT *_jlFillStackTop = NULL;
|
||||||
|
@ -797,6 +801,13 @@ void jlModStop(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JL_HAS_MODVOLUME
|
||||||
|
void jlModVolume(jbyte volume) {
|
||||||
|
(void)volume;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef JL_HAS_PALETTEDEFAULT
|
#ifndef JL_HAS_PALETTEDEFAULT
|
||||||
void jlPaletteDefault(void) {
|
void jlPaletteDefault(void) {
|
||||||
jbyte i;
|
jbyte i;
|
||||||
|
@ -882,6 +893,13 @@ void jlSoundStop(jlSoundT *sound) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JL_HAS_SOUNDSWAPCHANNELS
|
||||||
|
void jlSoundSwapChannels(jbool swap) {
|
||||||
|
_jlSwapChannels = swap;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef JL_HAS_STNFREE
|
#ifndef JL_HAS_STNFREE
|
||||||
void jlStnFree(jlStnT *stn) {
|
void jlStnFree(jlStnT *stn) {
|
||||||
if (stn != NULL) {
|
if (stn != NULL) {
|
||||||
|
|
|
@ -98,6 +98,7 @@ typedef unsigned int juint32;
|
||||||
#define JL_HAS_MODPAUSE
|
#define JL_HAS_MODPAUSE
|
||||||
#define JL_HAS_MODPLAY
|
#define JL_HAS_MODPLAY
|
||||||
#define JL_HAS_MODSTOP
|
#define JL_HAS_MODSTOP
|
||||||
|
#define JL_HAS_MODVOLUME
|
||||||
#define JL_HAS_PALETTESET
|
#define JL_HAS_PALETTESET
|
||||||
#define JL_HAS_PALETTESETFROMIMG
|
#define JL_HAS_PALETTESETFROMIMG
|
||||||
#define JL_HAS_SOUNDFREE
|
#define JL_HAS_SOUNDFREE
|
||||||
|
@ -142,6 +143,7 @@ typedef unsigned int juint32;
|
||||||
#define JL_HAS_MODPAUSE
|
#define JL_HAS_MODPAUSE
|
||||||
#define JL_HAS_MODPLAY
|
#define JL_HAS_MODPLAY
|
||||||
#define JL_HAS_MODSTOP
|
#define JL_HAS_MODSTOP
|
||||||
|
#define JL_HAS_MODVOLUME
|
||||||
#define JL_HAS_PALETTESET
|
#define JL_HAS_PALETTESET
|
||||||
#define JL_HAS_PALETTESETFROMIMG
|
#define JL_HAS_PALETTESETFROMIMG
|
||||||
#define JL_HAS_SOUNDFREE
|
#define JL_HAS_SOUNDFREE
|
||||||
|
@ -186,6 +188,7 @@ typedef unsigned int juint32;
|
||||||
#define JL_HAS_MODPAUSE
|
#define JL_HAS_MODPAUSE
|
||||||
#define JL_HAS_MODPLAY
|
#define JL_HAS_MODPLAY
|
||||||
#define JL_HAS_MODSTOP
|
#define JL_HAS_MODSTOP
|
||||||
|
#define JL_HAS_MODVOLUME
|
||||||
#define JL_HAS_PALETTESET
|
#define JL_HAS_PALETTESET
|
||||||
#define JL_HAS_PALETTESETFROMIMG
|
#define JL_HAS_PALETTESETFROMIMG
|
||||||
#define JL_HAS_SOUNDFREE
|
#define JL_HAS_SOUNDFREE
|
||||||
|
@ -440,6 +443,7 @@ jbool _jlModLoad(jlModT **mod, char *filename);
|
||||||
void jlModPause(void);
|
void jlModPause(void);
|
||||||
void jlModPlay(jlModT *mod);
|
void jlModPlay(jlModT *mod);
|
||||||
void jlModStop(void);
|
void jlModStop(void);
|
||||||
|
void jlModVolume(jbyte volume);
|
||||||
|
|
||||||
void jlPaletteDefault(void); //***TODO*** Treat palettes like we do "surfaces" - allow changing STAs or display
|
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"
|
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);
|
jbool _jlSoundLoad(jlSoundT **sound, char *filename);
|
||||||
void jlSoundPlay(jlSoundT *sound, jlSoundChannelE channel, jbyte volume);
|
void jlSoundPlay(jlSoundT *sound, jlSoundChannelE channel, jbyte volume);
|
||||||
void jlSoundStop(jlSoundT *sound);
|
void jlSoundStop(jlSoundT *sound);
|
||||||
|
void jlSoundSwapChannels(jbool swap);
|
||||||
|
|
||||||
void jlStnFree(jlStnT *stn);
|
void jlStnFree(jlStnT *stn);
|
||||||
#define jlStnLoad(stn, filename) _jlStnLoad((jlStnT **)&(stn), filename, __LINE__, (char *)__FILE__) // Syntatic Sugar
|
#define jlStnLoad(stn, filename) _jlStnLoad((jlStnT **)&(stn), filename, __LINE__, (char *)__FILE__) // Syntatic Sugar
|
||||||
|
|
|
@ -290,6 +290,7 @@ void musicTest(void) {
|
||||||
jlModT *music = NULL;
|
jlModT *music = NULL;
|
||||||
jlSoundT *sound1 = NULL;
|
jlSoundT *sound1 = NULL;
|
||||||
jlSoundT *sound2 = NULL;
|
jlSoundT *sound2 = NULL;
|
||||||
|
jbyte volume = 0;
|
||||||
|
|
||||||
if (!jlImgLoad(kanga, "kanga")) jlUtilDie("Unable to load kanga.img!");
|
if (!jlImgLoad(kanga, "kanga")) jlUtilDie("Unable to load kanga.img!");
|
||||||
if (!jlImgLoad(font, "font")) jlUtilDie("Unable to load font.img!");
|
if (!jlImgLoad(font, "font")) jlUtilDie("Unable to load font.img!");
|
||||||
|
@ -302,12 +303,17 @@ void musicTest(void) {
|
||||||
|
|
||||||
jlModPlay(music);
|
jlModPlay(music);
|
||||||
|
|
||||||
jlSoundPlay(sound2, CHANNEL_FRONT_RIGHT, 255);
|
//jlSoundSwapChannels(jtrue);
|
||||||
jlSoundPlay(sound1, CHANNEL_FRONT_LEFT, 255);
|
jlSoundPlay(sound1, CHANNEL_FRONT_LEFT, 255);
|
||||||
|
jlSoundPlay(sound2, CHANNEL_FRONT_RIGHT, 255);
|
||||||
|
|
||||||
while (!jlKeyPressed()) {
|
while (!jlKeyPressed()) {
|
||||||
fontPrint(font, NULL, 1, 1, "%dx%d %d %d ", jlGameGetAxis(0), jlGameGetAxis(1), jlGameGetButton(0), jlGameGetButton(1));
|
fontPrint(font, NULL, 1, 1, "%dx%d %d %d ", jlGameGetAxis(0), jlGameGetAxis(1), jlGameGetButton(0), jlGameGetButton(1));
|
||||||
jlDisplayPresent();
|
jlDisplayPresent();
|
||||||
|
if (volume < 255) {
|
||||||
|
volume++;
|
||||||
|
jlModVolume(volume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
jlKeyRead();
|
jlKeyRead();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue