blob: 5ccb03d82aa2c3a2a4c789726faaf5a75b510331 [file] [log] [blame] [edit]
#include <string>
#include <cstring>
#include <memory>
#include <cstdlib>
#include "audio-wave.hpp"
#include "glass.h"
/*
Wave example:
An example of an arbitrary waveform being played through the blit speaker.
This example, a runthrough:
Audio data:
The audio file has been converted to 22050Hz sample rate, then exported without its header.
(If a headered file is used, just read past that first. Try skipping the first 44 bytes).
You would preferably store files separate because uncompressed audio will use all your flash!
Here though, the raw wave to a c header using 'xxd -i glass.raw glass.h'
As the data could be long, or even infinite, we can fill the audio buffer via a callback.
Calling channels[n].trigger_attack() will run the playback and callback continuously until
either channels[n].trigger_release() or channels[n].off() is called.
*/
using namespace blit;
void buffCallBack(void *); //Declare our callback here instead of putting the whole thing here.
/* setup */
void init() {
// Setup channel
channels[0].waveforms = Waveform::WAVE; // Set type to WAVE
channels[0].callback_waveBufferRefresh = &buffCallBack; // Set callback address
screen.pen = Pen(0, 0, 0, 255);
screen.clear();
}
// Static wave config
static uint32_t wavSize = 0;
static uint16_t wavPos = 0;
static uint16_t wavSampleRate = 0;
static const uint16_t *wavSample;
// Called everytime audio buffer ends
void buffCallBack(void *) {
// Copy 64 bytes to the channel audio buffer
for (int x = 0; x < 64; x++) {
// If current sample position is greater than the sample length, fill the rest of the buffer with zeros.
// Note: The sample used here has an offset, so we adjust by 0x7f.
channels[0].wave_buffer[x] = (wavPos < wavSize) ? wavSample[wavPos] - 0x7f : 0;
// As the engine is 22050Hz, we can timestretch to match by incrementing our sample every other step (every even 'x')
if (wavSampleRate == 11025) {
if (x % 2) wavPos++;
} else {
wavPos++;
}
}
// For this example, clear the values
if (wavPos >= wavSize) {
channels[0].off(); // Stop playback of this channel.
//Clear buffer
wavSample = nullptr;
wavSize = 0;
wavPos = 0;
wavSampleRate = 0;
}
}
void render(uint32_t time_ms) {
screen.pen = Pen(0, 0, 0);
screen.clear();
screen.alpha = 255;
screen.pen = Pen(255, 255, 255);
screen.rectangle(Rect(0, 0, 320, 14));
screen.pen = Pen(0, 0, 0);
screen.text("Wave Example", minimal_font, Point(5, 4));
screen.pen = Pen(64, 64, 64);
screen.text("Press A to break screen.", minimal_font, Point(20, 60));
bool button_a = blit::buttons & blit::Button::A;
// If 'A' button pushed
if(button_a){
wavSample = glass_wav; // Set sample to the array in glass.h
wavSize = glass_wav_len; // Set the array length to the value in glass.h
channels[0].trigger_attack(); // Start the playback.
}
}
void update(uint32_t time_ms) {
}