/* * sound.h * * Created on: 03 ÿíâ. 2016 ã. * Author: Sergey */ #ifndef SOUND_H_ #define SOUND_H_ #include #include enum class SoundNodeType { Wave, Silence }; struct SoundNode { SoundNodeType type; uint32_t freq; uint32_t length; //in freq periods }; struct Notes { //First octave x100 mul static constexpr uint32_t values[] = { 26163, 27718, 29366, 31113, 32963, 34923, 36999, 39200, 41530, 44000, 46616, 49388}; static constexpr uint32_t C() {return values[0]; } static constexpr uint32_t C_d() {return values[1]; } static constexpr uint32_t D() {return values[2]; } static constexpr uint32_t D_d() {return values[3]; } static constexpr uint32_t E() {return values[4]; } static constexpr uint32_t F() {return values[5]; } static constexpr uint32_t F_d() {return values[6]; } static constexpr uint32_t G() {return values[7]; } static constexpr uint32_t G_d() {return values[8]; } static constexpr uint32_t A() {return values[9]; } static constexpr uint32_t B_b() {return values[10]; } static constexpr uint32_t B() {return values[11]; } }; //int16_t get_sine(uint8_t phase8); uint8_t get_sine(uint8_t phase8); template class SoundPlayer : public Base { public: uint8_t out; bool is_playing; SoundPlayer():out(0), is_playing(false), _loop(false), _nodes(nullptr), _nodes_count(0), _active_node(0), _sample_counter(0) { } void stop(){ if(is_playing){ Base::on_sound_stop(); } } template void play_sound(SoundNode(&nodes)[Count], bool loop = false){ play_sound(nodes, Count, loop); } void play_sound(SoundNode* nodes, size_t nodes_count, bool loop = false){ stop(); _loop = loop; out = 0; is_playing = true; _nodes = nodes; _nodes_count = nodes_count; _active_node = 0; _sample_counter = 0; Base::on_sound_play(); } void update(){ if(is_playing){ auto tmp = ((_sample_counter * 0x100 * (uint64_t)_nodes[_active_node].freq) / Base::get_sampling_rate()) / 100; if(_nodes[_active_node].type == SoundNodeType::Silence){ out = 0; } else { uint8_t sample_interp = (uint8_t)(tmp % 0x100); //out = sample_interp < 128 ? 0 : 0xff; out = (int32_t)get_sine(sample_interp); } _sample_counter++; if (_sample_counter >= _nodes[_active_node].length) { _active_node++; if (_active_node >= _nodes_count) { if(_loop){ _active_node = 0; }else{ is_playing = false; Base::on_sound_stop(); } } _sample_counter = 0; } } } private: bool _loop; SoundNode* _nodes; size_t _nodes_count; size_t _active_node; uint32_t _sample_counter; }; #endif /* SOUND_H_ */