-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Setting speaker states explicitly #6718
base: dev
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## dev #6718 +/- ##
==========================================
+ Coverage 53.70% 54.25% +0.54%
==========================================
Files 50 50
Lines 9408 9587 +179
Branches 1654 1689 +35
==========================================
+ Hits 5053 5201 +148
- Misses 4056 4062 +6
- Partials 299 324 +25 ☔ View full report in Codecov by Sentry. |
6527312
to
1f5cfd9
Compare
Hey there @jesserockz, mind taking a look at this pull request as it has been labeled with an integration ( |
I have been testing it, sinds last night (MLT) and it is much much stabler then before. |
esphome/components/speaker/speaker.h
Outdated
@@ -5,6 +5,7 @@ namespace speaker { | |||
|
|||
enum State : uint8_t { | |||
STATE_STOPPED = 0, | |||
STATE_WAITING_FOR_LOCK, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I did not add this here in the first place is that not all speakers will have a lock to wait for. The lock is specific to the i2s speaker platform only and really the i2s speaker should just stay in STARTING
state until it is actually ready then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue here is that the original solution did not finished correctly and that i found that the VA speaker buffer did got overflowed after some commands every time i tried. the audio was starting to get stuttered and breaking off.
The solution that @gnumpi suggested here, fixed this totally. The audio is now very stable and i do not see any buffer overflows anymore.
I understand what you are saying. An other solution would be that HA tells when there are no audio packages to receive anymore and that after the buffer is empty the speaker can be closed.
This was an suggestion i already wanted to make before @gnumpi created this solution for me.
See: https://discord.com/channels/429907082951524364/1229209995158225117
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree, I introduced this new state in order to not call try_lock when the lock is already owned while waiting for the task to setup the i2s driver. Sure, I could add an if clause to check if it is already owned, do you prefer this? On the other hand, platforms which don't need to wait for a resource could just skip this state and it could be called WAITING_FOR_RESOURCE, or something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have no problems with the solution itself in terms of functionality. Just that the Lock is specific to the i2s platforms.
The i2s media player has this for internal tracking:
enum I2SState : uint8_t {
I2S_STATE_STOPPED = 0,
I2S_STATE_STARTING,
I2S_STATE_RUNNING,
I2S_STATE_STOPPING,
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my suggestions are either:
- rename state to WAITING_FOR_RESOURCE (more general, can be skipped by platforms which don't need it)
- add a state between STARTING and RUNNING e.g. PREPARING
- add boolean to keep track if lock is already owned (while waiting for the i2s driver to be loaded inside the task)
which do you prefer? or do I miss a better solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer option 3 (or similar) because it keeps the starting implementation private to the i2s speaker. To the outside, its just starting until it is running.
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
Quiero desactivar
El El dom, 12 de may de 2024 a la(s) 4:53 p.m., Mischa Siekmann <
***@***.***> escribió:
… ***@***.**** commented on this pull request.
------------------------------
In esphome/components/speaker/speaker.h
<#6718 (comment)>:
> @@ -5,6 +5,7 @@ namespace speaker {
enum State : uint8_t {
STATE_STOPPED = 0,
+ STATE_WAITING_FOR_LOCK,
Yes I agree, I introduced this new state in order to not call try_lock
when the lock is already owned while waiting for the task to setup the i2s
driver. Sure, I could add an if clause to check if it is already owned, do
you prefer this? On the other hand, platforms which don't need to wait for
a resource could just skip this state and it could be called
WAITING_FOR_RESOURCE, or something like this.
—
Reply to this email directly, view it on GitHub
<#6718 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AL6XGDYBFKOWATWT725XVXLZB7XHDAVCNFSM6AAAAABHQ7BZYKVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDANJRGQ3DSNBQGM>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
this->start(); | ||
ESP_LOGD(TAG, "Called play while speaker not running."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RTTTL component using the speaker does expect that the speaker start when play() is called.
This breaks that component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just adjusted the RTTTL component to also call start and finish explicitly. Could you give it a try @nielsnl68 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
speaker/automation.h
(yaml action speaker.play
) will also need to be updated to call start
before play
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of having two methods for the speaker? The first 'play' is non-blocking and state less, and hence, it can be used as an action. It copies the data to the speaker buffer, starts the task and then stops the task when all data has been played. Consequently, this method can only play audio that fits into the speaker buffer at once. And the second method e.g. 'stream' can be called the same way as the current implementation, when the speaker (task) is running.
Co-authored-by: NP v/d Spek <github_mail@lumensoft.nl>
if (!this->speaker_->is_running()) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!this->speaker_->is_running()) { | |
return; | |
} |
This should not be here. The below code will add more wave sounds to the speaker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do you suggest to put it? Doesn't this prevent to start playing until the speaker is ready? And at the end of the audio the speaker running state should be unset only after the last samples have been send. Can you point me to the lines where you see the problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you want to be sure the RTTTL starts only when the speaker is has stopped.
Then we rearrange the code and a Starting and started mode like it is done in VA etc.
What does this implement/fix?
Solves timing issues introduced with sending TTS responses via API to speaker.
Types of changes
Related issue or feature (if applicable): fixes
Pull request in esphome-docs with documentation (if applicable): esphome/esphome-docs#
Test Environment
Example entry for
config.yaml
:# Example config.yaml
Checklist:
tests/
folder).If user exposed functionality or configuration variables are added/changed: