From dc9fd548c61346683d4b469bbe980d4d4d7ecb0c Mon Sep 17 00:00:00 2001 From: JailDoctor Date: Wed, 15 Sep 2021 13:58:23 +0200 Subject: [PATCH] basic song play, better vibrato, copy/paste note --- main.cpp | 82 ++++++++++++++++++++++++++++++++++++++++------------- song.cpp | 46 ++++++++++++++++++++++++++++++ song.h | 16 +++++++++-- tonegen.cpp | 8 ++++-- tonegen.h | 1 + 5 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 song.cpp diff --git a/main.cpp b/main.cpp index 46b31b7..66bded7 100755 --- a/main.cpp +++ b/main.cpp @@ -3,8 +3,9 @@ #include "audio.h" #include "draw.h" #include "note.h" +#include "song.h" -#define SOUND_DURATION 0.25f +#define SOUND_DURATION 0.0625f #define SOUND_NUM_SAMPLES SOUND_DURATION*SAMPLES_PER_SECOND #define SOUND_SIZE_IN_BYTES SOUND_NUM_SAMPLES*AUDIO_FORMAT_SIZE @@ -14,7 +15,8 @@ #define get_effect(x) (x & 0xF)*/ char note_names[12][3] = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " }; -Uint16 pattern[4][64]; +//Uint16 pattern[4][64]; +Song song; bool muted[4] = { false, false, false, false }; int selected_channel = 0; @@ -29,18 +31,33 @@ int current_effect = 0; toneGen channel[4]; SDL_AudioDeviceID sdlAudioDevice; Sint16 auxBuffer[512]; +uint16_t copied_note = 0; void audioCallback(void* userdata, Uint8* stream, int len) { Sint16* buffer = (Sint16*)stream; - int numBytesGenerated = channel[0].getSamples(len >> 1, buffer) * 2; - for (int i=1; i<4; ++i) { - channel[i].getSamples(len >> 1, auxBuffer); - for (int j=0; j> 1, buffer) * 2; + for (int i=1; i<4; ++i) { + channel[i].getSamples(len >> 1, auxBuffer); + for (int j=0; j> 1); + len -= numBytesGenerated; + song.Next(); + channel[0].setup(song.GetCurrentNote(0)); + channel[1].setup(song.GetCurrentNote(1)); + channel[2].setup(song.GetCurrentNote(2)); + channel[3].setup(song.GetCurrentNote(3)); + } else { + int rest = len - numBytesGenerated; + SDL_memset(&stream[numBytesGenerated], 0, rest); + SDL_PauseAudioDevice(sdlAudioDevice, 1); + return; + } + } else { return; } } } @@ -60,7 +77,7 @@ const char* get_zero_padded(const uint8_t num) { int main(int argc, char* argv[]) { for (int i=0; i<4; ++i) channel[i].setNoteLength(SOUND_NUM_SAMPLES); - pattern[0][0] = (34<<10) + (2<<8) + (7<<4) + 5; + song.SetCurrentNote(0, 0, (34<<10) + (2<<8) + (7<<4) + 5); SDL_Init(SDL_INIT_EVERYTHING); sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); @@ -172,16 +189,36 @@ int main(int argc, char* argv[]) { } } } - Note note(pattern[selected_channel][selected_row]); + Note note(song.GetCurrentNote(selected_channel, selected_row)); //uint8_t base_note = 1+(base_octave-2)*12; if ((key == SDL_SCANCODE_PERIOD) || (key == SDL_SCANCODE_DELETE)) note.Set(0); + if (key == SDL_SCANCODE_RETURN) copied_note = note.Get(); if (key == SDL_SCANCODE_SPACE) { - channel[0].setup(pattern[0][selected_row]); - channel[1].setup(pattern[1][selected_row]); - channel[2].setup(pattern[2][selected_row]); - channel[3].setup(pattern[3][selected_row]); + note.Set(copied_note); + channel[0].setup(note.Get()); + channel[1].setup(0); + channel[2].setup(0); + channel[3].setup(0); SDL_PauseAudioDevice(sdlAudioDevice, 0); } + if (key == SDL_SCANCODE_F4) { + channel[0].setup(song.GetCurrentNote(0, selected_row)); + channel[1].setup(song.GetCurrentNote(1, selected_row)); + channel[2].setup(song.GetCurrentNote(2, selected_row)); + channel[3].setup(song.GetCurrentNote(3, selected_row)); + SDL_PauseAudioDevice(sdlAudioDevice, 0); + } + if (key == SDL_SCANCODE_F5) { + song.Play(); + channel[0].setup(song.GetCurrentNote(0)); + channel[1].setup(song.GetCurrentNote(1)); + channel[2].setup(song.GetCurrentNote(2)); + channel[3].setup(song.GetCurrentNote(3)); + SDL_PauseAudioDevice(sdlAudioDevice, 0); + } + if (key == SDL_SCANCODE_F8) { + song.Stop(); + } if (selected_part==0) { bool m = true; switch(key) { @@ -201,6 +238,9 @@ int main(int argc, char* argv[]) { }; if (m) { channel[0].setup(note.Get()); + channel[1].setup(0); + channel[2].setup(0); + channel[3].setup(0); SDL_PauseAudioDevice(sdlAudioDevice, 0); } } @@ -265,7 +305,7 @@ int main(int argc, char* argv[]) { default: break; }; } - pattern[selected_channel][selected_row] = note.Get(); + song.SetCurrentNote(selected_channel, selected_row, note.Get()); } } draw_clear(color_dark_grey); @@ -286,7 +326,9 @@ int main(int argc, char* argv[]) { for (int x=0; x<4; ++x) { yp = 15; for (int y=0; y<32; ++y) { - if (x == selected_channel && (y+scroll) == selected_row) { + if ((song.IsPlaying()) && (y+scroll == song.GetCurrentRow())) { + draw_fill(xp-1, yp-1, 32, 7, color_yellow); + } else if (x == selected_channel && (y+scroll) == selected_row) { draw_fill(xp-1, yp-1, 32, 7, color_dark_blue); switch (selected_part) { case 0: draw_fill(xp-1, yp-1, 11, 7, color_yellow); break; @@ -296,7 +338,7 @@ int main(int argc, char* argv[]) { case 4: draw_fill(25+xp, yp-1, 6, 7, color_yellow); break; } } - Note note(pattern[x][y+scroll]); + Note note(song.GetCurrentNote(x, y+scroll)); //Uint16 current_note = pattern[x][y]; if (note.GetAbsoluteNote() == 0) { uint8_t color = color_dark_blue; diff --git a/song.cpp b/song.cpp new file mode 100644 index 0000000..69a2aa3 --- /dev/null +++ b/song.cpp @@ -0,0 +1,46 @@ +#include "song.h" + +Song::Song() { + this->playing = false; + this->current_pattern = 0; + this->current_row = 0; +} + +void Song::SetCurrentPatternNum(const int pattern_num) { + this->current_pattern = pattern_num; +} + +void Song::SetCurrentNote(const int channel, const int row, const uint16_t note) { + this->pattern[channel][row] = note; +} + +const int Song::GetCurrentPatternNum() { + return this->current_pattern; +} + +const int Song::GetCurrentRow() { + return this->current_row; +} + +uint16_t Song::GetCurrentNote(const int channel, int row) { + return this->pattern[channel][row<0?this->current_row:row]; +} + +void Song::Play() { + this->current_row = 0; + this->playing = true; +} + +void Song::Stop() { + this->playing = false; +} + +const bool Song::IsPlaying() { + return this->playing; +} + +void Song::Next() { + this->current_row++; + if (this->current_row == 64) this->current_row = 0; +} + \ No newline at end of file diff --git a/song.h b/song.h index b131f7c..2086b37 100644 --- a/song.h +++ b/song.h @@ -8,9 +8,21 @@ class Song { public: Song(); + void SetCurrentPatternNum(const int pattern_num); + void SetCurrentNote(const int channel, const int row, const uint16_t note); - uint16_t GetCurrentNote(const int channel); + const int GetCurrentPatternNum(); + const int GetCurrentRow(); + uint16_t GetCurrentNote(const int channel, int row = -1); + + void Play(); + void Stop(); + const bool IsPlaying(); + void Next(); private: - std::vector patterns; + bool playing; + int current_pattern; + int current_row; + uint16_t pattern[4][64]; }; diff --git a/tonegen.cpp b/tonegen.cpp index 48ff1c2..2d19eaf 100755 --- a/tonegen.cpp +++ b/tonegen.cpp @@ -9,7 +9,7 @@ toneGen::toneGen() { this->note = 34; this->instrument = CHIPTUNE_INSTRUMENT_NOISE; - this->volume = 15; + this->volume = 0; this->effect = CHIPTUNE_EFFECT_FADEOUT; this->current_volume = this->nominal_volume = 1.0f; @@ -21,6 +21,7 @@ toneGen::toneGen() { this->old_df = this->df = notes[this->note]; this->f = -AUDIO_FORMAT_MAX_VALUE; + this->vibrato_counter = 0; } void toneGen::setNoteLength(const int note_length) { @@ -30,6 +31,8 @@ void toneGen::setNoteLength(const int note_length) { void toneGen::setup(const uint8_t note, const uint8_t instrument, const uint8_t volume, const uint8_t effect) { this->current_pos = 0; + if (note == 0) return; + this->note = note; this->instrument = instrument; this->volume = volume; @@ -52,12 +55,13 @@ const int toneGen::getSamples(const int numSamples, Sint16 *buffer) { for (int i=0; ieffect) { case CHIPTUNE_EFFECT_NONE: break; case CHIPTUNE_EFFECT_VIBRATO: - f += SDL_sinf((i+this->current_pos)/1000)*15; + f += SDL_sinf(vibrato_counter)*8; 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; } diff --git a/tonegen.h b/tonegen.h index e6c9878..86c80c4 100755 --- a/tonegen.h +++ b/tonegen.h @@ -28,4 +28,5 @@ class toneGen { Sint16 df, old_df, f; int note_length; int current_pos; + float vibrato_counter; };