bbcmicrobit / micropython

Port of MicroPython for the BBC micro:bit
https://microbit-micropython.readthedocs.io
Other
598 stars 284 forks source link

Music/Speech Pin detection problem #419

Open ntoll opened 7 years ago

ntoll commented 7 years ago

The micro:bit music module doesn't appear to detect that the speaker is connected to pins 0 and 1 (as it should) causing it to be silent or very quiet. However, once speech takes place the pins are correctly configured. I believe there is a detection step in the speech module that doesn't appear to occur for the music module.

To re-create, plug in a speaker to pins 0 and 1 and, try the following REPL interaction:

>>> import music
>>> music.play(music.NYAN)  # very very quiet
>>> import speech
>>> speech.say("Hello")  # at the correct volume
>>> music.play(music.NYAN)  # at the correct volume

Music plays at the correct volume if I connect the speaker to pins 0 and GND (as we used to have to do). But part of the point of the new pin code / audio work was that it would correctly detect the use of non-ground pins (so speech would work better) and audio output would be at the correct volume.

I hope this makes sense. Happy to answer questions.

dpgeorge commented 7 years ago

The audio and speech modules use a totally different backend compared to the music module. The former use a custom PWM implementation that can be "double ended", whereas the latter uses standard PWM, which can only be "single ended". The audio module plays audio frames but the music module just plays notes, so they aren't that compatible. Probably the best thing to do would be to modify the audio module so it can play pure notes/frequencies, and migrate the music module to use this new feature.

@markshannon may have a different opinion/idea.

ntoll commented 7 years ago

Yup, that was my understanding except for the belief that this migration of the music/audio module had taken place already. @markshannon ..?

markshannon commented 7 years ago

The music module uses the PWM module at the moment. Porting it to the audio module and adding some "instruments" is on my to do list.

jaustin commented 6 years ago

Testing on the v1 branch, I see the following:

So, here it looks like speech.say() is changing the configuration of P1 to be GND (perhaps as opposed to an input?) and the volume effect for music is a side effect (IE before when using music on P0/P1 we were driving against an input and after speech we're driving against GND).

Here's a testcase to verify that theory

from microbit import *
import music
music.play(music.BADDY) # This plays quietly (v0.9, v1)
pin1.write_digital(0)
music.play(music.JUMP_UP) # This plays loudly (v0.9, v1)
import speech
speech.say("This speech is first") # This sounds distorted and poor on V0.9, fine on v1
music.play(music.JUMP_DOWN) # This does not play on v0.9, fine on v1
speech.say("This speech is second") # This sounds differently distorted on v0.9, fine on v1

There's a bit of a decision here: if we want to support using P0/P1 for music, we should make the music module configure P1 as a gnd.

However, I don't think we should do that. I think we should move to always using P0/GND for music and speech.

In our tests, the music and speech performance was very similar for v1 branch using P0/P1 and P0/GND, but the simplicity of it all being the same, and the same as MakeCode/everything else.

(@carlosperate and I noted that speech.say() also appears to clobber P2, for some reason? He's about to file that...)

jaustin commented 6 years ago

(for anyone reading this thread via email, I've edited the previous message/comment to make it significantly more sane, the original comment had paragraphs out of order and seemed like I was contradicting myself. Also a P1/P0 typo. Sorry for the noise)

dpgeorge commented 6 years ago

However, I don't think we should do that. I think we should move to always using P0/GND for music and speech.

In our tests, the music and speech performance was very similar for v1 branch using P0/P1 and P0/GND, but the simplicity of it all being the same, and the same as MakeCode/everything else.

Using P0/P1 as a differential pair for music/sound/speech should make it roughly twice as loud, and I remember it doing that at some point in the history of the code. Because sound is very quiet using P0/GND I think it's a good feature to have the option of using P0/P1. @jaustin If it was fixed so that P0/P1 was much louder than P0/GND would it be worth keeping it as an option even though it differs to MakeCode/others?

ntoll commented 6 years ago

As I understand it, P0/P1 is needed for Mark's audio module to work in any case, and it's the only way Speech will work (and it's always worked this way anyway). -1 to @jaustin's suggestion of P0/GND simply because it would break all the things that already work in the other way (like speech).

markshannon commented 6 years ago

Speech should work with pin/GND as well as pin/pin. Using pin/pin will produce more power (roughly 4 times as much) and the sound quality will be a bit better.

carlosperate commented 6 years ago

Having P0/GND would work in all cases, so it woudn't break anything. Having P0/P1 with the music module (which doesn't use the differential pair) currently would not work properly, unless P1 was configured to ground (which it doesn't currently do, but could be done, although that's a different conversation), but that's fine as long as the documentation clearly shows music is P0/GND (which it does).

During the tests were were carring out, I don't think we were seeing such a significant volume improvement, and we were not seeing P1 mirroring as a differential pair of P0, so I think we need to double check this is working as expected.