commit 0ceccb0d5d60e968439a65aeedfb999741899ed5 Author: Raimon Zamora Date: Thu Sep 2 22:22:01 2021 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..90dfd1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode/* +*.dll +*.exe diff --git a/audio.h b/audio.h new file mode 100755 index 0000000..9a43d23 --- /dev/null +++ b/audio.h @@ -0,0 +1,8 @@ +#pragma once + +#define AUDIO_FORMAT AUDIO_S16 +#define AUDIO_FORMAT_TYPE Sint16 +#define AUDIO_FORMAT_SIZE sizeof(AUDIO_FORMAT_TYPE) +#define AUDIO_FORMAT_MAX_VALUE 32767 + +#define SAMPLES_PER_SECOND 44100 diff --git a/font.bmp b/font.bmp new file mode 100644 index 0000000..d46476a Binary files /dev/null and b/font.bmp differ diff --git a/main.cpp b/main.cpp new file mode 100755 index 0000000..095ac3e --- /dev/null +++ b/main.cpp @@ -0,0 +1,88 @@ +#include +#include "tonegen.h" +#include "audio.h" + +#define SOUND_DURATION 0.25f +#define SOUND_NUM_SAMPLES SOUND_DURATION*SAMPLES_PER_SECOND +#define SOUND_SIZE_IN_BYTES SOUND_NUM_SAMPLES*AUDIO_FORMAT_SIZE + +SDL_AudioSpec audioSpec{SAMPLES_PER_SECOND, AUDIO_FORMAT, 1, 0, 512, 0, 0, NULL, NULL}; + +int main(int argc, char* argv[]) { + SDL_Init(SDL_INIT_EVERYTHING); + SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); + + AUDIO_FORMAT_TYPE beeps[int(SOUND_NUM_SAMPLES*8)]; + AUDIO_FORMAT_TYPE beeps2[int(SOUND_NUM_SAMPLES*8)]; + AUDIO_FORMAT_TYPE *pointer = beeps; + + toneGen tonegen(SOUND_NUM_SAMPLES); + + tonegen.setup(22, CHIPTUNE_INSTRUMENT_TRIANGLE, 13, CHIPTUNE_EFFECT_DROP); + int numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(32, CHIPTUNE_INSTRUMENT_SQUARE, 0, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(32, CHIPTUNE_INSTRUMENT_NOISE, 4, CHIPTUNE_EFFECT_FADEOUT); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(32, CHIPTUNE_INSTRUMENT_SQUARE, 0, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(22, CHIPTUNE_INSTRUMENT_TRIANGLE, 13, CHIPTUNE_EFFECT_DROP); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(22, CHIPTUNE_INSTRUMENT_TRIANGLE, 13, CHIPTUNE_EFFECT_DROP); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(32, CHIPTUNE_INSTRUMENT_NOISE, 4, CHIPTUNE_EFFECT_FADEOUT); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(32, CHIPTUNE_INSTRUMENT_SQUARE, 0, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + + pointer = beeps2; + tonegen.setup(35, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(37, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(39, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(40, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(42, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(44, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(46, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + tonegen.setup(47, CHIPTUNE_INSTRUMENT_SQUARE, 1, CHIPTUNE_EFFECT_NONE); + numSamples = tonegen.getSamples(SOUND_NUM_SAMPLES, pointer); pointer += int(SOUND_NUM_SAMPLES); + + for (int i=0; i + +Sint16 notes[64]; + +toneGen::toneGen(const int note_length) { + this->note_length = note_length; + this->current_pos = 0; + + this->note = 32; + this->instrument = CHIPTUNE_INSTRUMENT_NOISE; + this->volume = 15; + this->effect = CHIPTUNE_EFFECT_FADEOUT; + + this->current_volume = this->nominal_volume = 1.0f; + + for (int i=0; i<64; ++i) { + const float NOTE_FREQ = 440 * pow(1.059463094359, i-32); + notes[i] = 65536 / int(SAMPLES_PER_SECOND/NOTE_FREQ); + } + + this->old_df = this->df = notes[this->note]; + this->f = -AUDIO_FORMAT_MAX_VALUE; +} + +void toneGen::setup(const uint8_t note, const uint8_t instrument, const uint8_t volume, const uint8_t effect) { + this->current_pos = 0; + + this->note = note; + this->instrument = instrument; + this->volume = volume; + this->effect = effect; + + this->nominal_volume = float(volume) / 15.0f; + this->current_volume = this->effect == CHIPTUNE_EFFECT_FADEIN ? 0.0f : this->nominal_volume; + + this->old_df = this->df; + this->df = notes[this->note]; + this->f = -AUDIO_FORMAT_MAX_VALUE * this->current_volume; +} + +void toneGen::setup(const uint16_t tracker_note) { + setup(tracker_note >> 10, (tracker_note >> 8) & 0x03, (tracker_note >> 4) & 0x0F, tracker_note & 0x0F ); +} + +const int toneGen::getSamples(const int numSamples, Sint16 *buffer) { + const int actual_samples_generated = SDL_min(numSamples, this->note_length-this->current_pos); + + for (int i=0; ieffect) { + case CHIPTUNE_EFFECT_NONE: + break; + case CHIPTUNE_EFFECT_VIBRATO: + f += SDL_sinf((i+this->current_pos)/1000)*15; + break; + case CHIPTUNE_EFFECT_DROP: + if (((i+this->current_pos)%15)==0 && df != 0) { df--; if (df < 100) this->current_volume = this->nominal_volume*df*0.01f; } + if (df == 0) { buffer[i] = 0; continue; } + break; + case CHIPTUNE_EFFECT_FADEOUT: + if (this->current_volume > 0) this->current_volume -= (this->nominal_volume/float(this->note_length)); + break; + case CHIPTUNE_EFFECT_FADEIN: + if (this->current_volume < this->nominal_volume) this->current_volume += (this->nominal_volume/float(this->note_length)); + break; + } + + buffer[i] = f; + + Sint32 temp; + switch (this->instrument) { + case CHIPTUNE_INSTRUMENT_SAWTOOTH: + break; + case CHIPTUNE_INSTRUMENT_SQUARE: + buffer[i] = buffer[i] > 0 ? AUDIO_FORMAT_MAX_VALUE : -AUDIO_FORMAT_MAX_VALUE; + break; + case CHIPTUNE_INSTRUMENT_TRIANGLE: + temp = buffer[i]; + buffer[i] = buffer[i] < 0 ? ((temp+AUDIO_FORMAT_MAX_VALUE)*2)-AUDIO_FORMAT_MAX_VALUE : (AUDIO_FORMAT_MAX_VALUE*2-temp*2)-AUDIO_FORMAT_MAX_VALUE; + break; + case CHIPTUNE_INSTRUMENT_NOISE: + buffer[i] = (rand()*2)-AUDIO_FORMAT_MAX_VALUE; + break; + } + buffer[i] *= this->current_volume; + } + + this->current_pos += actual_samples_generated; + return actual_samples_generated; +} diff --git a/tonegen.h b/tonegen.h new file mode 100755 index 0000000..ddc3f44 --- /dev/null +++ b/tonegen.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#define CHIPTUNE_EFFECT_NONE 0 +#define CHIPTUNE_EFFECT_SLIDE 1 +#define CHIPTUNE_EFFECT_VIBRATO 2 +#define CHIPTUNE_EFFECT_DROP 3 +#define CHIPTUNE_EFFECT_FADEIN 4 +#define CHIPTUNE_EFFECT_FADEOUT 5 + +#define CHIPTUNE_INSTRUMENT_SAWTOOTH 0 +#define CHIPTUNE_INSTRUMENT_SQUARE 1 +#define CHIPTUNE_INSTRUMENT_TRIANGLE 2 +#define CHIPTUNE_INSTRUMENT_NOISE 3 + +class toneGen { + public: + toneGen(const int note_length); + void setup(const uint8_t note, const uint8_t instrument, const uint8_t volume, const uint8_t effect); + void setup(const uint16_t tracker_note); + const int getSamples(const int numSamples, Sint16 *buffer); + + private: + uint8_t note, instrument, volume, effect; + float nominal_volume, current_volume; + Sint16 df, old_df, f; + int note_length; + int current_pos; +};