mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 16:38:16 +01:00
Add RTTTL volume control. (#5968)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
37138d4f28
commit
c43c9ad1c5
3 changed files with 32 additions and 15 deletions
|
@ -12,6 +12,7 @@ from esphome.const import (
|
|||
CONF_PLATFORM,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_SPEAKER,
|
||||
CONF_GAIN,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -38,6 +39,7 @@ CONFIG_SCHEMA = cv.All(
|
|||
cv.GenerateID(CONF_ID): cv.declare_id(Rtttl),
|
||||
cv.Optional(CONF_OUTPUT): cv.use_id(FloatOutput),
|
||||
cv.Optional(CONF_SPEAKER): cv.use_id(Speaker),
|
||||
cv.Optional(CONF_GAIN, default="0.6"): cv.percentage,
|
||||
cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
|
@ -98,6 +100,8 @@ async def to_code(config):
|
|||
out = await cg.get_variable(config[CONF_SPEAKER])
|
||||
cg.add(var.set_speaker(out))
|
||||
|
||||
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
|
|
@ -16,7 +16,7 @@ static const uint16_t NOTES[] = {0, 262, 277, 294, 311, 330, 349, 370,
|
|||
1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217,
|
||||
2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951};
|
||||
|
||||
static const uint16_t I2S_SPEED = 1600;
|
||||
static const uint16_t I2S_SPEED = 1000;
|
||||
|
||||
#undef HALF_PI
|
||||
static const double HALF_PI = 1.5707963267948966192313216916398;
|
||||
|
@ -136,7 +136,7 @@ void Rtttl::loop() {
|
|||
if (this->samples_per_wave_ != 0 && this->samples_sent_ >= this->samples_gap_) { // Play note//
|
||||
rem = ((this->samples_sent_ << 10) % this->samples_per_wave_) * (360.0 / this->samples_per_wave_);
|
||||
|
||||
int16_t val = 8192 * sin(deg2rad(rem));
|
||||
int16_t val = (49152 * this->gain_) * sin(deg2rad(rem));
|
||||
|
||||
sample[x].left = val;
|
||||
sample[x].right = val;
|
||||
|
@ -269,7 +269,7 @@ void Rtttl::loop() {
|
|||
}
|
||||
if (this->output_freq_ != 0) {
|
||||
this->output_->update_frequency(this->output_freq_);
|
||||
this->output_->set_level(0.5);
|
||||
this->output_->set_level(this->gain_);
|
||||
} else {
|
||||
this->output_->set_level(0.0);
|
||||
}
|
||||
|
@ -278,18 +278,23 @@ void Rtttl::loop() {
|
|||
#ifdef USE_SPEAKER
|
||||
if (this->speaker_ != nullptr) {
|
||||
this->samples_sent_ = 0;
|
||||
this->samples_count_ = (this->sample_rate_ * this->note_duration_) / I2S_SPEED;
|
||||
// Convert from frequency in Hz to high and low samples in fixed point
|
||||
this->samples_gap_ = 0;
|
||||
this->samples_per_wave_ = 0;
|
||||
this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1600; //(ms);
|
||||
if (need_note_gap) {
|
||||
this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1600; //(ms);
|
||||
}
|
||||
if (this->output_freq_ != 0) {
|
||||
this->samples_per_wave_ = (this->sample_rate_ << 10) / this->output_freq_;
|
||||
} else {
|
||||
this->samples_per_wave_ = 0;
|
||||
}
|
||||
if (need_note_gap) {
|
||||
this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / I2S_SPEED;
|
||||
} else {
|
||||
this->samples_gap_ = 0;
|
||||
|
||||
// make sure there is enough samples to add a full last sinus.
|
||||
uint16_t division = ((this->samples_count_ << 10) / this->samples_per_wave_) + 1;
|
||||
uint16_t x = this->samples_count_;
|
||||
this->samples_count_ = (division * this->samples_per_wave_);
|
||||
ESP_LOGD(TAG, "play time old: %d div: %d new: %d %d", x, division, this->samples_count_, this->samples_per_wave_);
|
||||
this->samples_count_ = this->samples_count_ >> 10;
|
||||
}
|
||||
// Convert from frequency in Hz to high and low samples in fixed point
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace esphome {
|
|||
namespace rtttl {
|
||||
|
||||
#ifdef USE_SPEAKER
|
||||
static const size_t SAMPLE_BUFFER_SIZE = 256;
|
||||
static const size_t SAMPLE_BUFFER_SIZE = 512;
|
||||
|
||||
struct SpeakerSample {
|
||||
int16_t left{0};
|
||||
|
@ -31,6 +31,13 @@ class Rtttl : public Component {
|
|||
#ifdef USE_SPEAKER
|
||||
void set_speaker(speaker::Speaker *speaker) { this->speaker_ = speaker; }
|
||||
#endif
|
||||
void set_gain(float gain) {
|
||||
if (gain < 0.1f)
|
||||
gain = 0.1f;
|
||||
if (gain > 1.0f)
|
||||
gain = 1.0f;
|
||||
this->gain_ = gain;
|
||||
}
|
||||
void play(std::string rtttl);
|
||||
void stop();
|
||||
void dump_config() override;
|
||||
|
@ -60,6 +67,7 @@ class Rtttl : public Component {
|
|||
uint16_t note_duration_;
|
||||
|
||||
uint32_t output_freq_;
|
||||
float gain_{0.6f};
|
||||
|
||||
#ifdef USE_OUTPUT
|
||||
output::FloatOutput *output_;
|
||||
|
@ -68,13 +76,13 @@ class Rtttl : public Component {
|
|||
void play_output_();
|
||||
|
||||
#ifdef USE_SPEAKER
|
||||
speaker::Speaker *speaker_;
|
||||
void play_speaker_();
|
||||
speaker::Speaker *speaker_{nullptr};
|
||||
int sample_rate_{16000};
|
||||
int samples_per_wave_{0};
|
||||
int samples_sent_{0};
|
||||
int samples_count_{0};
|
||||
int samples_gap_{0};
|
||||
|
||||
#endif
|
||||
|
||||
CallbackManager<void()> on_finished_playback_callback_;
|
||||
|
|
Loading…
Reference in a new issue