Add RTTTL volume control. (#5968)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
NP v/d Spek 2024-02-27 23:31:33 +01:00 committed by GitHub
parent 37138d4f28
commit c43c9ad1c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 15 deletions

View file

@ -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)

View file

@ -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

View file

@ -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_;