Commit e9fd1973 authored by Jack's avatar Jack
Browse files

working on sound rendering

parent 3d5b532d
......@@ -113,8 +113,8 @@ void GameView::render()
if (machine.code().hasInit())
machine.code().init();
/*machine.sound().init();
machine.sound().resume();*/
//machine.sound().init();
//machine.sound().resume();
/*for (int i = 0; i < 32; ++i)
machine.circ(64, 64, i+1, (r8::color_t)(i % 15 + 1));*/
......
......@@ -156,16 +156,16 @@ DSP dsp(44100);
constexpr float PULSE_WAVE_DEFAULT_DUTY = 1 / 3.0f;
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;
int16_t* rendered = nullptr;
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)
{
rendered = new int16_t[44100 * 3];
......@@ -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);
if (position < 44100 * 3)
......@@ -214,8 +214,39 @@ void APU::init()
}
}
Sound ssound;
SoundState sstate;
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);
}
......@@ -223,3 +254,29 @@ void APU::close()
{
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 @@
#include "defines.h"
#include "common.h"
#include <array>
#include <SDL_audio.h>
#if SOUND_ENABLED
......@@ -13,6 +14,7 @@ namespace retro8
{
using volume_t = int32_t;
using pitch_t = int32_t;
using frequency_t = int32_t;
enum class Waveform
{
......@@ -24,16 +26,44 @@ namespace retro8
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
{
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
uint16_t value;
bool useSfx() const { return value & 0x8000; }
Effect effect() const { return Effect((value >> 12) & 0b111); }
Waveform waveform() const { return Waveform((value >> 6) & 0b111); }
volume_t volume() const { return (value >> 9) & 0b111; }
pitch_t pitch() const { return value & 0x111111; }
Effect effect() const { return Effect((value & EffectMask) >> EffectShift); }
Waveform waveform() const { return Waveform((value & WaveformMask) >> WaveformShift); }
volume_t volume() const { return (value & VolumeMask) >> VolumeShift; }
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
......@@ -45,6 +75,13 @@ namespace retro8
uint8_t loopEnd;
};
struct SoundState
{
const Sound* sound;
uint32_t sample;
uint32_t position; // absolute
};
class DSP
{
private:
......@@ -77,6 +114,8 @@ namespace retro8
void resume();
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