*
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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_ */
|
||||
Reference in New Issue
Block a user