117 lines
2.6 KiB
C++
117 lines
2.6 KiB
C++
/*
|
|
* sound.h
|
|
*
|
|
* Created on: 03 ÿíâ. 2016 ã.
|
|
* Author: Sergey
|
|
*/
|
|
|
|
#ifndef SOUND_H_
|
|
#define SOUND_H_
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
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<typename Base>
|
|
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<size_t Count>
|
|
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_ */
|