Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Tone Generator
- #include <SDL2/SDL.h>
- #include <fstream>
- #include "kaelWaveforms.h"
- #include <iostream>
- #include <vector>
- #include <algorithm>
- uint8_t AMPLITUDE = 1<<sizeof(AMPLITUDE)*7;
- const uint channels = 2;
- const uint16_t SAMPLE_RATE = 32768;
- const uint16_t FREQUENCY = 1;
- //order does not matter in enum or map
- enum class WaveformKey {
- csine,
- noise,
- pulse,
- saw,
- sine,
- square,
- triangle
- };
- std::map<std::string, WaveformKey> waveformKeyMap{
- {"csine", WaveformKey::csine},
- {"noise", WaveformKey::noise},
- {"pulse", WaveformKey::pulse},
- {"saw", WaveformKey::saw},
- {"sine", WaveformKey::sine},
- {"square", WaveformKey::square},
- {"triangle", WaveformKey::triangle}
- };
- //I gave up trying to get functional, lambdas, variadic and fucntion pointers to work
- //Waveform functions
- template <typename T, typename T2>
- T waveformFunction(WaveformKey index, T2 num, T arg0 = 0, T arg1 = 0) {
- switch (index) {
- case WaveformKey::csine:
- return ukaelCSine<T>(num);
- case WaveformKey::noise:
- return ukaelNoise<T, T2>(num);
- case WaveformKey::pulse:
- return ukaelPulse<T>(num, arg0);
- case WaveformKey::saw:
- return ukaelSaw<T>(num);
- case WaveformKey::sine:
- return ukaelSine<T>(num);
- case WaveformKey::square:
- return ukaelSquare<T>(num);
- case WaveformKey::triangle:
- return ukaelTriangle<T>(num);
- default:
- return T(0);
- }
- }
- //generate and store waveform to buffer. 16, 32 and 64 bit varaints require bug fixing
- //waveform template <return type, input type>
- template <typename T, typename U>
- void generateTone(T* buffer, const ufrac<uint32_t>& freq, uint64_t length, std::string waveformKey, T arg0=0, T arg1=0) {
- WaveformKey enumKey = waveformKeyMap[waveformKey]; //find key index
- T value;
- for (uint64_t i = 0; i < length; ++i) {
- value = waveformFunction<T,U>(enumKey,(i/freq.a*freq.b),arg0,arg1); //call generator function for each sample
- value = value * (T)AMPLITUDE / ((T)~0) + (((T)~0) - (T)AMPLITUDE) / 2; // amplitude
- buffer[i] = static_cast<T>(value); //store to buffer
- }
- return;
- }
- int main() {
- AMPLITUDE=1<<sizeof(AMPLITUDE)*5; //1/8 that your ears don't bleed in preview
- SDL_Init(SDL_INIT_AUDIO);
- SDL_AudioSpec auspec;
- auspec.freq = SAMPLE_RATE;
- auspec.format = AUDIO_U8;
- auspec.channels = 2;
- auspec.callback = nullptr;
- SDL_AudioSpec obtainedSpec;
- SDL_OpenAudio(&auspec, &obtainedSpec);
- uint64_t csamples = 32768; //generated samples per channel
- uint64_t mixedSize = csamples*auspec.channels; //mixed channel size
- uint64_t channelSize = csamples; //single channel size
- uint16_t mixChannels=7; //mixing channels
- mixedSize*=mixChannels;
- //init vector
- std::vector<std::vector<uint8_t>> channel(mixChannels);
- for (uint i = 0; i < mixChannels; ++i) {
- channel[i].resize(channelSize);
- }
- uint8_t arg0=32; //argument for pulse tone
- int ci=0; //channel index
- //generate 1 second of all functions
- for (const auto& pair : waveformKeyMap) {
- const std::string& key = pair.first; //find tested function
- generateTone<uint8_t,uint16_t>(channel[ci++].data(), ufrac{1U, 1U}, channelSize, key,arg0);
- }
- //mixed channel
- std::vector<uint8_t> mixed(mixedSize);
- //concat
- for (const auto& c : channel) {
- mixed.insert(mixed.end(), c.begin(), c.end());
- }
- try {//clear file
- std::ofstream audioRaw("audio.raw", std::ios::binary);
- audioRaw<<0;
- audioRaw.close();
- } catch (const std::exception& e) {
- std::cerr << "Failed to write audio file: " << e.what() << std::endl;
- }
- mixed.resize(auspec.channels*channelSize);
- for (int k=0; k<mixChannels;k+=1) {
- // mono to stereo
- for (uint64_t i = 0; i < channelSize; i++ ) {
- for(int j=0;j<auspec.channels;j++){
- mixed[ auspec.channels * i + 0 ] = channel[k][i];
- mixed[ auspec.channels * i + j ] = channel[k][i];
- }
- }
- try {//print to file
- std::ofstream audioRaw("audio.raw", std::ios::binary | std::ios::app);
- audioRaw.write(reinterpret_cast<const char*>(mixed.data()), auspec.channels*channelSize);
- audioRaw.close();
- } catch (const std::exception& e) {
- std::cerr << "Failed to write audio file: " << e.what() << std::endl;
- }
- // Queue the audio buffer
- SDL_QueueAudio(1, mixed.data(), auspec.channels*channelSize);
- // Start audio playback
- SDL_PauseAudio(0);
- }
- uint waitTime = 1000*channelSize*mixChannels;
- SDL_Delay(waitTime/SAMPLE_RATE);
- SDL_PauseAudio(1);
- // Delete the 2D vector
- for (size_t i = 0; i < channel.size(); ++i) {
- channel[i].clear(); // Clear the individual row vector
- }
- channel.clear(); // Clear the outer vector
- mixed.clear();
- return 0;
- }
Advertisement
Comments
-
- https://pastebin.com/kNqN9z2Q
-
Comment was deleted
Add Comment
Please, Sign In to add comment
Advertisement