first commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.vscode/*
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
8
audio.h
Executable file
8
audio.h
Executable file
@@ -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
|
||||||
88
main.cpp
Executable file
88
main.cpp
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#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<SOUND_NUM_SAMPLES*8;++i) {
|
||||||
|
beeps[i] += beeps2[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Window *sdlWindow = SDL_CreateWindow("Mus", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1102, 700, SDL_WINDOW_SHOWN);
|
||||||
|
SDL_Renderer *sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(sdlRenderer, 255, 255, 255, 255);
|
||||||
|
|
||||||
|
int last_x = 0, last_y = 120;
|
||||||
|
for (int x=0; x<1102; ++x) {
|
||||||
|
int y = 700 - (350+300*(float(beeps[x*10])/float(AUDIO_FORMAT_MAX_VALUE)));
|
||||||
|
SDL_RenderDrawLine(sdlRenderer, x, y, last_x, last_y);
|
||||||
|
last_x = x; last_y = y;
|
||||||
|
}
|
||||||
|
SDL_RenderPresent(sdlRenderer);
|
||||||
|
|
||||||
|
SDL_QueueAudio(sdlAudioDevice, &beeps[0], SOUND_SIZE_IN_BYTES*8);
|
||||||
|
SDL_PauseAudioDevice(sdlAudioDevice, 0);
|
||||||
|
|
||||||
|
bool exit = false;
|
||||||
|
SDL_Event sdlEvent;
|
||||||
|
while (!exit) {
|
||||||
|
while (SDL_PollEvent(&sdlEvent)) {
|
||||||
|
if (sdlEvent.type == SDL_QUIT) { exit = true; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DestroyRenderer(sdlRenderer);
|
||||||
|
SDL_DestroyWindow(sdlWindow);
|
||||||
|
SDL_Quit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
93
tonegen.cpp
Executable file
93
tonegen.cpp
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "tonegen.h"
|
||||||
|
#include "audio.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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; i<actual_samples_generated;++i) {
|
||||||
|
f += df;
|
||||||
|
|
||||||
|
switch (this->effect) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
30
tonegen.h
Executable file
30
tonegen.h
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user