Commit e9fd1973 authored by Jack's avatar Jack
Browse files

working on sound rendering

parent 3d5b532d
...@@ -113,8 +113,8 @@ void GameView::render() ...@@ -113,8 +113,8 @@ void GameView::render()
if (machine.code().hasInit()) if (machine.code().hasInit())
machine.code().init(); machine.code().init();
/*machine.sound().init(); //machine.sound().init();
machine.sound().resume();*/ //machine.sound().resume();
/*for (int i = 0; i < 32; ++i) /*for (int i = 0; i < 32; ++i)
machine.circ(64, 64, i+1, (r8::color_t)(i % 15 + 1));*/ machine.circ(64, 64, i+1, (r8::color_t)(i % 15 + 1));*/
......
...@@ -156,16 +156,16 @@ DSP dsp(44100); ...@@ -156,16 +156,16 @@ DSP dsp(44100);
constexpr float PULSE_WAVE_DEFAULT_DUTY = 1 / 3.0f; constexpr float PULSE_WAVE_DEFAULT_DUTY = 1 / 3.0f;
constexpr float ORGAN_DEFAULT_COEFFICIENT = 0.5f; constexpr float ORGAN_DEFAULT_COEFFICIENT = 0.5f;
enum Note { C, CS, D, DS, E, F, FS, G, GS, A, AS, B };
const std::array<float, 12> NoteTable = {
130.81f, 138.59f, 146.83f, 155.56f, 164.81f, 174.61f, 185.00f, 196.00, 207.65, 220.0, 233.08, 246.94
};
size_t position = 0; size_t position = 0;
int16_t* rendered = nullptr; int16_t* rendered = nullptr;
void audio_callback(void* data, uint8_t* cbuffer, int length) void audio_callback(void* data, uint8_t* cbuffer, int length)
{ {
APU* apu = static_cast<APU*>(data);
int16_t* buffer = reinterpret_cast<int16_t*>(cbuffer);
apu->renderSounds(buffer, length / sizeof(int16_t));
return;
if (!rendered) if (!rendered)
{ {
rendered = new int16_t[44100 * 3]; rendered = new int16_t[44100 * 3];
...@@ -175,7 +175,7 @@ void audio_callback(void* data, uint8_t* cbuffer, int length) ...@@ -175,7 +175,7 @@ void audio_callback(void* data, uint8_t* cbuffer, int length)
} }
//APU* apu = static_cast<APU*>(data); //
//int16_t* buffer = reinterpret_cast<int16_t*>(cbuffer); //int16_t* buffer = reinterpret_cast<int16_t*>(cbuffer);
if (position < 44100 * 3) if (position < 44100 * 3)
...@@ -214,12 +214,69 @@ void APU::init() ...@@ -214,12 +214,69 @@ void APU::init()
} }
} }
Sound ssound;
SoundState sstate;
void APU::resume() void APU::resume()
{ {
ssound.speed = 32;
ssound.samples[0].setPitch(Note::pitch(Tone::E, 2));
ssound.samples[1].setPitch(Note::pitch(Tone::E, 2));
ssound.samples[2].setPitch(Note::pitch(Tone::F, 2));
ssound.samples[3].setPitch(Note::pitch(Tone::G, 2));
ssound.samples[4].setPitch(Note::pitch(Tone::G, 2));
ssound.samples[5].setPitch(Note::pitch(Tone::F, 2));
ssound.samples[6].setPitch(Note::pitch(Tone::E, 2));
ssound.samples[7].setPitch(Note::pitch(Tone::D, 2));
ssound.samples[8].setPitch(Note::pitch(Tone::C, 2));
ssound.samples[9].setPitch(Note::pitch(Tone::C, 2));
ssound.samples[10].setPitch(Note::pitch(Tone::D, 2));
ssound.samples[11].setPitch(Note::pitch(Tone::E, 2));
ssound.samples[12].setPitch(Note::pitch(Tone::E, 2));
ssound.samples[13].setPitch(Note::pitch(Tone::D, 2));
for (size_t i = 0; i < ssound.samples.size(); ++i)
{
ssound.samples[i].setVolume(7);
ssound.samples[i].setWaveform(Waveform::ORGAN);
printf("%d ", Note::frequency(ssound.samples[i].pitch()));
}
sstate.sound = &ssound;
sstate.position = 0;
sstate.sample = 0;
SDL_PauseAudioDevice(device, false); SDL_PauseAudioDevice(device, false);
} }
void APU::close() void APU::close()
{ {
SDL_CloseAudioDevice(device); SDL_CloseAudioDevice(device);
}
void APU::renderSounds(int16_t* dest, size_t samples)
{
constexpr size_t rate = 44100;
size_t samplePerTick = (44100 / 128) * (sstate.sound->speed + 1);
while (samples > 0)
{
/* generate the maximum amount of samples available for same note */
// TODO: optimize if next note is equal to current
size_t available = std::min(samples, samplePerTick - (sstate.position % samplePerTick));
const SoundSample& sample = sstate.sound->samples[sstate.sample];
/* render samples */
dsp.squareWave(Note::frequency(sample.pitch()), (4096 / 8) * sample.volume(), 0, sstate.position, dest, samples);
samples -= available;
dest += available;
sstate.position += available;
sstate.sample = sstate.position / samplePerTick;
}
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "defines.h" #include "defines.h"
#include "common.h" #include "common.h"
#include <array>
#include <SDL_audio.h> #include <SDL_audio.h>
#if SOUND_ENABLED #if SOUND_ENABLED
...@@ -13,6 +14,7 @@ namespace retro8 ...@@ -13,6 +14,7 @@ namespace retro8
{ {
using volume_t = int32_t; using volume_t = int32_t;
using pitch_t = int32_t; using pitch_t = int32_t;
using frequency_t = int32_t;
enum class Waveform enum class Waveform
{ {
...@@ -24,16 +26,44 @@ namespace retro8 ...@@ -24,16 +26,44 @@ namespace retro8
NONE, SLIDE, VIBRATO, DROP, FADE_IN, FADE_OUT, ARPEGGIO_FAST, ARPEGGIO_SLOW NONE, SLIDE, VIBRATO, DROP, FADE_IN, FADE_OUT, ARPEGGIO_FAST, ARPEGGIO_SLOW
}; };
enum class Tone { C, CS, D, DS, E, F, FS, G, GS, A, AS, B };
struct Note
{
private:
constexpr static std::array<float, 12> frequencies = {
130.81f, 138.59f, 146.83f, 155.56f, 164.81f, 174.61f, 185.00f, 196.00, 207.65, 220.0, 233.08, 246.94
};
public:
static pitch_t pitch(Tone tone, int32_t octave = 1) { return pitch_t(tone) + octave * 12; }
static frequency_t frequency(Tone tone, int32_t octave = 1) { return frequencies[size_t(tone)] * octave; };
static frequency_t frequency(pitch_t pitch) { return frequencies[pitch % 12] * (1 + pitch / 12); }
};
struct SoundSample struct SoundSample
{ {
static constexpr uint16_t EffectMask = 0x7000;
static constexpr uint16_t VolumeMask = 0x0E00;
static constexpr uint16_t WaveformMask = 0x01C0;
static constexpr uint16_t PitchMask = 0x003F;
static constexpr uint32_t EffectShift = 12;
static constexpr uint32_t VolumeShift = 9;
static constexpr uint32_t WaveformShift = 6;
//TODO: endianness is a fail here //TODO: endianness is a fail here
uint16_t value; uint16_t value;
bool useSfx() const { return value & 0x8000; } bool useSfx() const { return value & 0x8000; }
Effect effect() const { return Effect((value >> 12) & 0b111); } Effect effect() const { return Effect((value & EffectMask) >> EffectShift); }
Waveform waveform() const { return Waveform((value >> 6) & 0b111); } Waveform waveform() const { return Waveform((value & WaveformMask) >> WaveformShift); }
volume_t volume() const { return (value >> 9) & 0b111; } volume_t volume() const { return (value & VolumeMask) >> VolumeShift; }
pitch_t pitch() const { return value & 0x111111; } pitch_t pitch() const { return value & PitchMask; }
void setPitch(pitch_t pitch) { value = (value & ~PitchMask) | pitch; }
void setVolume(volume_t volume) { value = (value & ~VolumeMask) | (volume << VolumeShift); }
void setEffect(Effect effect) { value = (value & ~EffectMask) | (uint16_t(effect) << EffectShift); }
void setWaveform(Waveform waveform) { value = (value & ~WaveformMask) | (uint16_t(waveform) << WaveformShift); }
}; };
struct Sound struct Sound
...@@ -44,6 +74,13 @@ namespace retro8 ...@@ -44,6 +74,13 @@ namespace retro8
uint8_t loopStart; uint8_t loopStart;
uint8_t loopEnd; uint8_t loopEnd;
}; };
struct SoundState
{
const Sound* sound;
uint32_t sample;
uint32_t position; // absolute
};
class DSP class DSP
{ {
...@@ -77,6 +114,8 @@ namespace retro8 ...@@ -77,6 +114,8 @@ namespace retro8
void resume(); void resume();
void pause(); void pause();
void renderSounds(int16_t* dest, size_t samples);
}; };
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment