Skip to content

Commit

Permalink
build fixes, more oscillators, instrument cleanup/fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ahigerd committed Sep 26, 2022
1 parent 20146f1 commit b4020eb
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 35 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
build
build_win
include
seq2wav
seq2wav_d
seq2wav_test*
*.dll
*.a
*.so
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
include config.mak

all: seq2wav$(EXE)
all: seq2wav_test$(EXE)

debug: seq2wav_d$(EXE)
debug: seq2wav_test_d$(EXE)

static: $(BUILDPATH)/libseq2wav.a

Expand All @@ -13,7 +13,7 @@ includes: $(INCLUDES)
build/Makefile.d: $(wildcard src/*.cpp src/*/*.cpp src/*.h src/*/*.h) Makefile src/Makefile
$(MAKE) -C src ../build/Makefile.d

seq2wav$(EXE) seq2wav_d$(EXE): src/Makefile build/Makefile.d
seq2wav_test$(EXE) seq2wav_test_d$(EXE): src/Makefile build/Makefile.d
$(MAKE) -C src ../$@

$(BUILDPATH)/libseq2wav.a $(BUILDPATH)/libseq2wav_d.a: src/Makefile build/Makefile.d $(INCLUDES)
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ include ../config.mak

SOURCES = $(filter-out main.cpp, $(wildcard *.cpp */*.cpp))

../seq2wav$(EXE): ../$(BUILDPATH)/main.o ../$(BUILDPATH)/libseq2wav.a
../seq2wav_test$(EXE): ../$(BUILDPATH)/main.o ../$(BUILDPATH)/libseq2wav.a
$(CXX) -o $@ $^

../seq2wav_d$(EXE): ../$(BUILDPATH)/main_d.o ../$(BUILDPATH)/libseq2wav_d.$(DLL)
../seq2wav_test_d$(EXE): ../$(BUILDPATH)/main_d.o ../$(BUILDPATH)/libseq2wav_d.$(DLL)
$(CXX) -o $@ $^

../$(BUILDPATH)/libseq2wav.a: $(patsubst %.cpp, ../$(BUILDPATH)/%.o, $(SOURCES)) ../$(BUILDPATH)/Makefile.d
Expand Down
7 changes: 4 additions & 3 deletions src/codec/riffcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,17 @@ SampleData* RiffCodec::decodeRange(std::vector<uint8_t>::const_iterator start, s
if (offset + 8 + chunkSize > size) {
throw std::runtime_error("RIFF chunk data is invalid");
}
offset += 8;
if (magic == 'fmt ') {
fmt = WaveFormatEx(start + offset + 8, start + offset + chunkSize);
fmt = WaveFormatEx(start + offset, start + offset + chunkSize);
} else if (magic == 'data') {
data.insert(
data.end(),
buffer + (offset + 8),
buffer + offset,
buffer + (offset + chunkSize)
);
}
offset += 8 + chunkSize;
offset += chunkSize;
}
std::unique_ptr<ICodec> codec;
if (fmt.format == 1) {
Expand Down
6 changes: 4 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#include "seq/testsequence.h"
#include "synth/channel.h"
#include "synth/synthcontext.h"
#include "s2wcontext.h"
#include "riffwriter.h"
#include <iostream>

int main(int argc, char** argv) {
TestSequence seq;
SynthContext ctx(44100);
S2WContext s2w;
TestSequence seq(&s2w);
SynthContext ctx(&s2w, 44100);
int numTracks = seq.numTracks();
for (int i = 0; i < numTracks; i++) {
ctx.channels.emplace_back(new Channel(&ctx, seq.getTrack(i)));
Expand Down
12 changes: 12 additions & 0 deletions src/seq/sequenceevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ OscillatorEvent::OscillatorEvent()
// initializers only
}

InstrumentNoteEvent::InstrumentNoteEvent()
: pitch(69)
{
// initializers only
}

AudioNodeEvent::AudioNodeEvent(std::shared_ptr<::AudioNode> node)
: node(node)
{
Expand All @@ -109,3 +115,9 @@ ChannelEvent::ChannelEvent(uint32_t param, double value)
{
// initializers only
}

ChannelEvent::ChannelEvent(uint32_t param, uint64_t intValue)
: param(param), intValue(intValue)
{
// initializers only
}
21 changes: 18 additions & 3 deletions src/seq/sequenceevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define S2W_SEQUENCEEVENT_H

#include <cstdint>
#include <vector>
#include <memory>
#include "synth/audionode.h"

Expand All @@ -12,10 +13,11 @@ class SequenceEvent {
enum EventTypes {
Sample,
Oscillator,
InstrumentNote,
AudioNode,
Channel,
Modulator,
Kill,
Channel,
AudioNode,
UserBase,
};

Expand Down Expand Up @@ -138,6 +140,15 @@ class OscillatorEvent : public NoteEvent<OscillatorEvent, SequenceEvent::Oscilla
double frequency;
};

class InstrumentNoteEvent : public NoteEvent<InstrumentNoteEvent, SequenceEvent::InstrumentNote> {
public:
InstrumentNoteEvent();

double pitch;
std::vector<double> floatParams;
std::vector<uint64_t> intParams;
};

class AudioNodeEvent : public NoteEvent<AudioNodeEvent, SequenceEvent::AudioNode> {
public:
AudioNodeEvent(std::shared_ptr<::AudioNode> node);
Expand Down Expand Up @@ -165,9 +176,13 @@ class KillEvent : public BaseEvent<KillEvent, SequenceEvent::Kill> {
class ChannelEvent : public BaseEvent<ChannelEvent, SequenceEvent::Channel> {
public:
ChannelEvent(uint32_t param, double value);
ChannelEvent(uint32_t param, uint64_t intValue);

uint32_t param;
double value;
union {
double value;
uint64_t intValue;
};
};

#endif
17 changes: 16 additions & 1 deletion src/seq/testsequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "itrack.h"
#include "utility.h"
#include "codec/riffcodec.h"
#include "synth/oscillator.h"

static const double testNotes[] = { 440, 554.36, 659.26, 880, 1108.73 };

Expand All @@ -14,6 +15,11 @@ TestSequence::TestSequence(S2WContext* ctx) : BaseSequence(ctx)
addTrack(new BasicTrack());
}

static const BaseOscillator::WaveformPreset waveforms[] = {
BaseOscillator::Triangle,
BaseOscillator::Square25,
BaseOscillator::Square50,
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
OscillatorEvent* event = new OscillatorEvent;
Expand Down Expand Up @@ -57,9 +63,18 @@ TestSequence::TestSequence(S2WContext* ctx) : BaseSequence(ctx)

OscillatorEvent* e = new OscillatorEvent;
e->setEnvelope(.25, .5, .5, .5, .5, .5);
e->waveformID = -1;
e->waveformID = BaseOscillator::Sine;
e->duration = 2.5;
e->timestamp = 1.0 + sample->duration() * 3;
tracks[0]->addEvent(e);

for (int i = 0; i < BaseOscillator::NumPresets; i++) {
OscillatorEvent* e = new OscillatorEvent;
e->waveformID = i;
e->frequency = (i >= BaseOscillator::Noise ? 880.0 : 440.0);
e->duration = .5;
e->volume = .5;
e->timestamp = 4.5 + sample->duration() * 3 + i * .75;
tracks[0]->addEvent(e);
}
}
12 changes: 11 additions & 1 deletion src/synth/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ Channel::Note::Note()
// initializers only
}

Channel::Note::Note(std::shared_ptr<BaseNoteEvent> event, AudioNode* source, double duration)
: Note(event, std::shared_ptr<AudioNode>(source), duration)
{
// forwarded constructor only
}

Channel::Note::Note(std::shared_ptr<BaseNoteEvent> event, std::shared_ptr<AudioNode> source, double duration)
: event(event), source(source), duration(duration), kill(false)
{
Expand Down Expand Up @@ -51,7 +57,11 @@ uint32_t Channel::fillBuffer(std::vector<int16_t>& buffer, ssize_t numSamples)
break;
}
if (auto chEvent = ChannelEvent::castShared(event)) {
instrument->channelEvent(this, chEvent);
if (chEvent->param == 'inst') {
instrument = ctx->getInstrument(chEvent->intValue);
} else {
instrument->channelEvent(this, chEvent);
}
} else if (auto modEvent = ModulatorEvent::castShared(event)) {
instrument->modulatorEvent(this, modEvent);
} else if (auto noteEvent = BaseNoteEvent::castShared(event)) {
Expand Down
1 change: 1 addition & 0 deletions src/synth/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Channel : public AudioParamContainer {

struct Note {
Note();
Note(std::shared_ptr<BaseNoteEvent> event, AudioNode* source, double duration);
Note(std::shared_ptr<BaseNoteEvent> event, std::shared_ptr<AudioNode> source, double duration);
Note(const Note& other) = default;
Note(Note&& other) = default;
Expand Down
11 changes: 6 additions & 5 deletions src/synth/iinstrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Channel::Note* DefaultInstrument::noteEvent(Channel* channel, std::shared_ptr<Ba
if (AudioNodeEvent* nodeEvent = event->cast<AudioNodeEvent>()) {
node = nodeEvent->node;
} else if (OscillatorEvent* oscEvent = event->cast<OscillatorEvent>()) {
BaseOscillator* osc = BaseOscillator::create(channel->ctx, oscEvent->waveformID, oscEvent->frequency, oscEvent->volume, oscEvent->pan);
BaseOscillator* osc = BaseOscillator::create(channel->ctx, BaseOscillator::WaveformPreset(oscEvent->waveformID), oscEvent->frequency, oscEvent->volume, oscEvent->pan);
duration = oscEvent->duration;
node.reset(osc);
} else if (SampleEvent* sampEvent = event->cast<SampleEvent>()) {
Expand All @@ -58,18 +58,19 @@ Channel::Note* DefaultInstrument::noteEvent(Channel* channel, std::shared_ptr<Ba
duration = sampleData->duration();
}
} else {
std::cerr << "ERROR: unhandled user event" << std::endl;
std::cerr << "ERROR: unhandled instrument or user event" << std::endl;
return nullptr;
}
Channel::Note* note = new Channel::Note(std::shared_ptr<BaseNoteEvent>(event), node, duration);
Channel::Note* note = new Channel::Note(event, node, duration);
if (event->useEnvelope) {
applyEnvelope(channel, note, event);
applyEnvelope(channel, note);
}
return note;
}

void DefaultInstrument::applyEnvelope(Channel* channel, Channel::Note* note, std::shared_ptr<BaseNoteEvent> event)
void DefaultInstrument::applyEnvelope(Channel* channel, Channel::Note* note)
{
const auto& event = note->event;
Envelope* env = new Envelope(channel->ctx, event->attack, event->hold, event->decay, event->sustain, event->fade, event->release);
env->expAttack = event->expAttack;
env->expDecay = event->expDecay;
Expand Down
2 changes: 1 addition & 1 deletion src/synth/iinstrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DefaultInstrument : public IInstrument {
public:
virtual Channel::Note* noteEvent(Channel* channel, std::shared_ptr<BaseNoteEvent> event);

void applyEnvelope(Channel* channel, Channel::Note* note, std::shared_ptr<BaseNoteEvent> event);
void applyEnvelope(Channel* channel, Channel::Note* note);
};

#endif
76 changes: 67 additions & 9 deletions src/synth/oscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,52 @@
#include <cmath>
#include <iostream>

BaseOscillator* BaseOscillator::create(const SynthContext* ctx, uint64_t waveformID, double frequency, double amplitude, double pan)
BaseOscillator* BaseOscillator::create(const SynthContext* ctx, BaseOscillator::WaveformPreset waveform, double frequency, double amplitude, double pan)
{
BaseOscillator* osc;
switch(waveformID) {
case 0:
switch (waveform) {
case Triangle:
osc = new TriangleOscillator(ctx);
break;
case NESTriangle:
osc = new TriangleOscillator(ctx, 16, true);
break;
case Sawtooth:
osc = new SawtoothOscillator(ctx);
break;
case Square50:
osc = new SquareOscillator(ctx, 0.5);
break;
case 1:
case Square75:
osc = new SquareOscillator(ctx, 0.75);
break;
case 2:
case Square25:
osc = new SquareOscillator(ctx, 0.25);
break;
case 3:
case Square125:
osc = new SquareOscillator(ctx, 0.125);
break;
case 4:
osc = new TriangleOscillator(ctx);
case Noise:
osc = new NoiseOscillator(ctx);
break;
case LinearNoise:
osc = new NoiseOscillator(ctx, NoiseOscillator::Linear);
break;
case 5:
case CosineNoise:
osc = new NoiseOscillator(ctx, NoiseOscillator::Cosine);
break;
case NESNoise:
osc = new NESNoiseOscillator(ctx);
break;
case NESNoise93:
osc = new NESNoise93Oscillator(ctx);
break;
case GBNoise:
osc = new GBNoiseOscillator(ctx);
break;
case GBNoise127:
osc = new GBNoise127Oscillator(ctx);
break;
default:
osc = new SineOscillator(ctx);
break;
Expand Down Expand Up @@ -62,6 +86,7 @@ int16_t BaseOscillator::generateSample(double time, int channel)

SineOscillator::SineOscillator(const SynthContext* ctx) : BaseOscillator(ctx)
{
// initializers only
}

double SineOscillator::calcSample(double)
Expand All @@ -80,6 +105,17 @@ double SquareOscillator::calcSample(double time)
return phase < dutyCycle->valueAt(time) ? 1.0 : -1.0;
}

SawtoothOscillator::SawtoothOscillator(const SynthContext* ctx)
: BaseOscillator(ctx)
{
// initializers only
}

double SawtoothOscillator::calcSample(double time)
{
return 2.0 * (phase - int64_t(phase) - 0.5);
}

TriangleOscillator::TriangleOscillator(const SynthContext* ctx, int quantize, bool skew)
: BaseOscillator(ctx), quantize(quantize), skew(skew)
{
Expand Down Expand Up @@ -107,6 +143,28 @@ double TriangleOscillator::calcSample(double)
return level * 2.0 - 1.0;
}

NoiseOscillator::NoiseOscillator(const SynthContext* ctx, Smoothing smoothing)
: BaseOscillator(ctx), smoothing(smoothing), lastPhase(0), lastLevel(0), nextLevel(0)
{
// initializers only
}

double NoiseOscillator::calcSample(double)
{
if (lastPhase > phase) {
lastLevel = nextLevel;
nextLevel = std::rand() / (RAND_MAX / 2.0) - 1.0;
}
lastPhase = phase;
if (smoothing == None) {
return nextLevel;
} else if (smoothing == Linear) {
return lerp(lastLevel, nextLevel, phase);
} else {
return lerp(nextLevel, lastLevel, fastCos(phase * M_PI) * 0.5 + 0.5);
}
}

NESNoiseOscillator::NESNoiseOscillator(const SynthContext* ctx)
: BaseOscillator(ctx), state(1), lastPhase(0)
{
Expand Down
Loading

0 comments on commit b4020eb

Please sign in to comment.