Feel the noise on a Raspberry Pi Pico - learn to play .wav and .mp3 files in CircuitPython

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
rock stars of python this is Brock G and it's time to make some noise we're going to connect a simple speaker with an audio plug to a Raspberry Pi Pico you'll see we can do this with alligator clips no special Barrel style audio receiver Jack is required and you'll see that you can use the same technique with headphones that contain this type of plug and we're going to learn how we can play both wave files and MP3 files we'll get some tips on setting up audio files for playback in circuit Python and we'll have some fun challenges where you can use your skills to hear encouragement from perhaps the Galaxy's greatest teacher and along the way we'll get more practice with the d-bounce button and we'll learn how to write shorter code using the ternary operator so python pad ones let's code in this tutorial I'm using a speaker with its own power source and that prevents us from having to mess with additional speaker power amplifiers and other things that make the build more complex and here I'm using what's called a hamburger speaker it's especially useful because it has a built-in rechargeable battery for portable projects and it can be charged or powered from a USB cable that comes with it these are pretty inexpensive and they're sold by lots of vendors but if you have any speaker that has its own power in this standard pin style audio plug maybe an external cell phone speaker or even a pair of plug-in headphones then you can use those as well and all you need to do is clip two additional wires to this standard audio plug just clip your ground wire to the base of the sleeve of the plug and the digital out wire should go to the tip now one additional thing to note this basic wiring encoding setup doesn't allow us to control the volume programmatically if you want manual volume control use a speaker that has its own volume control hamburger speakers often have just a low high volume setting but many speakers with this kind of Jack will have a volume knob for more fine grain loudness control it is possible to add additional Hardware like an amplifier and in a future lesson we'll cover the audio mixer Library which will give us some control over the volume of the speaker but for this tutorial we're going to use the easiest setup that involves the least amount of work complexity and additional Hardware here's a wiring diagram to show how to connect the speaker to my Pico W now I'm using two alligator clips with a pin at the other end the tip of the speaker's plug Clips to the wire I'm using for for audio input the other end goes to any of the Pico's GP digital pins and the ground wire Clips to the base or sleeve of the audio plug and that can go to any of the Pico's ground pins now remember there's no power in this build because I'm using a speaker that has its own built-in power supply this hamburger speaker has a built-in rechargeable battery and it can also plug into a USB port for continuous power if you're using the wiring scheme I'm showing in this lesson for most decent audio output you will want a speaker that's got its own power source you can also use headphones with a standard audio plug although if you can't override stereo to Mono you might only hear audio through one ear so to play a sound file we first need a sound file on our board now I've got some sounds for us to use at this URL bit.ly circuit python-school Dash files this is an open Google Drive so just right click or two finger click on the sounds folder and select download and it'll either go to your downloads folder or my browser asks me where I want to save it I'll save it to my desktop then find the sounds folder you just downloaded and open it up now unfortunately if you've been following along with these tutorials you probably don't have enough space on your pico for all these files in the setup video I asked you to use lots of different Library files now if you know you're not going to be using a library file you can actually delete them temporarily and then add them later on when you need them but what I'm going to do instead is just use one of these files so I'm going to head over to my Pico remember that's the circuit PI drive and I'm going to create a new folder on circuit Pi named sounds all lowercase to do that in the Mac you just right click or two finger click and then select new folder remember we're calling the sounds all lowercase then I'm going to drag the file 1.wave from the folder that I downloaded into the new sounds folder on my Pico if you've done this right you should have a folder called sounds on your circuit Pi volume with a file called wand dot wave inside of it now if you want to set up your own sound files know that circuit python expects wave files saved with the following specs they need to be mono files not stereo now files should be saved as 22 kilohertz and saved as 16 bit files now for a newbie or even an experienced user those terms might not be familiar but fear not if you want to convert an audio file to this format you can download the free audacity software it's available for both Mac and windows and here's where you'll find the settings to convert the files to the format I just explained so if you open audacity stereo down to Mono is under the tracks menu you'll use a menu in the lower left hand corner to convert down to 22 kilohertz that'll be listed as 22 050 then the file menu will let you export the file as a wave file in the box that pops up should allow you to select the 16-bit format just know that you don't have a lot of storage on most circuit python boards most boards have two megabytes Max and that includes your circuit python programs so you'll want to make sure that your files are small there are some add-on boards that will let you store larger files I'll also have a tutorial on my channel on how you can add additional Hardware to add a Micro SD card for additional gigabytes of extra storage in your Raspberry Pi Pico board look for that in the playlist on my YouTube channel if it's not there yet it will be soon now to write code to get our wired speaker to play our sound file we first import the libraries we need boarded from audio core we're going to import WAV file note how this is capitalized and from audio pwmio we're also going to import pwm audio out as audio out so that'll get the pwm audio out class from the audio pwmio library and it'll let us refer to that in our code as the name audio out also make sure you get these capitalizations right too now for those of you that have worked with our earlier tutorials on the circuit playground blue fruit we use these same import statements but here's where we write even less code than we did with the cpb there are four extra lines of code that we had to enter on the cpb to set up the internal speaker but here all we need to do is create an audio out object passing in the name of the pin that's connected to the tip of our speaker's audio jack for me that's board.gp14 and I'm going to name the object that's created here simply audio all lowercase but now very important you also want to make sure that you set the path as a string that contains the name of the folder that holds your sound files on your pico board so for us that's just sounds followed by a slash remember strings are always in double quotes and then we have our standard play underscore sound function that we used in the circuit playground and if you're new to this this we Define our function using the keyword def the function's named play sound we're going to pass in the name of the file that we want to play so we can see how we call this in our code once the function's set up we pass in the string wand dot wave down here because that's the name of the file that we want to play and this function is super reusable so you can copy and paste it whenever you want to play wav files on your pico but just so you know what's happening here we open the file at the path that's the folder that we defined up here and we RB or read in the binary data from the file at that path with the file name and call that wave underscore file then we set up a WAV file object using the data that we just read in and we call this new object wave then we use the audio object to find up here and we call its built-in play function it's play Method and we use that to play wave the WAV file we just created and the while audio dot playing Loop just causes our code to hang around and not advance until we're done playing the file now one more thing to note if you want to do additional things while the sound plays like animate neopixels or move Servo motor then you can put code to do that here replacing the pass statement or you could write it as a separate function and just call that function here in place of the pass statement so let's go this up and see if we can get this magical wand sound playing from our board so over and move we're going to cut up a file to play wave files from the Raspberry Pi Pico we're going to import time comma board comma digital i o and from audio core we're going to import WAV file and one more import we have to from audio pwmio import capital P capital W capital m capital A audio capital O out as capital A audio capital O out so make sure you get the Caps right and now let's create an audio out object and set a path where our sounds can be found and we'll do that by saying audio equals audio out capital a capital O and in parentheses I'm going to say board.gp14 because I've got the wire that's clipped to the tip of my speaker plug plugged into pin gp14 so if you're plugged into a different pin make sure that you add that pin's name here then I'll add the path variable which contains the folder where our sound files are stored and that's going to be path equals and in double quotes sounds slash now two things to remember one you can name the folder that holds your sound anything but this string needs to be spelled exactly the same as your folder name I've seen students waste a lot of time on errors because they forgot for example to add an S at the end of a folder name or they got the wrong capitalization and the second thing to remember is to make sure that you add the slash at the end the slash is a separator between your folder name and the file name which we pass into the function when we call it now if you ever get an error like this no such file or directory that means the file couldn't be found so either the folder isn't spelled properly in the path or you're missing your slash or the sound file on your folder is spelled differently from the file name you're using in your code or your folder simply doesn't have the sound file you're trying to play so if you ever get this error these are the things you need to check then let's define our play sound function and this is the same play sound function that we used in our previous circuit playground exercises if you did those we'll say def space play underscore sound in parentheses file name that's the string that we're passing in make sure you get a colon at the end mush it indent the next line very important and then on the next line with open and in parentheses path plus file name comma in quotes RB close parenthesis as wave underscore file colon so what this is going to do is it's going to try to open the file name at the path and read in the binary ones or zeros that make up that file and it's going to store it in a variable wave underscore file then on the line below this and again move should indent here as well we'll say wave equals wave file capital W capital F and in parentheses we pass in wave underscore file the ones and zeros that we got when we opened the path above now what we do here is we turn those ones and zeros into a valid WAV file and then down below we can say audio which is the audio out object we created above dot play make sure you say dot play instead of dot playing sometimes moo tries to trick you into writing.playing and then between parentheses pass in wave the WAV file we created above that'll start playing the sound and then underneath we'll say while audio dot playing colon then indented on the line below I'm going to say pass but this is where you can add any code that you want to run while your sound is playing so if you have led animation code put it in here if you're moving a Servo when a sound is playing put that in here as well you can also put that code in a separate function and just call the function here instead of the line that says pass and the code we've written above is very reusable so anytime you want to play a WAV file you can just copy and paste this code and you're good to go then rather than using a while true Loop we'll just play the sound once and then a program will end then make sure you outdent all the way so you're not inside the play function that we just defined and we'll call that function with play underscore sound and in parentheses we'll pass in the name of the sound that we want to play the name has to be a string so between double quotes we'll say wand.wav we open the serial Monitor and listen up as I save this as code.bi to my circuit Pi volume and we hear the lovely and magical one sound every time we click on Save we run the code again and we hear that sound again now before we move on let's save this code to our circuit python school folder as play wave sounds on a Pico then I'll close this tab and reload code.pi on my Pico and now we're going to learn how to play MP3 files so why do we even have these two file types well they are different wav files are an uncompressed file format so these files are larger and they take up more space but they're referred to as lossless files meaning that there is no quality loss when we create a WAV file now MP3 files are compressed these files are smaller but the compression can cause quality loss so we refer to MP3 as a lossy file encoder you can set some parameters when converting a file to MP3 so that you minimize the quality lost but if you need a higher quality file or MP3 simply aren't performing for you consider waves now it used to be that we only had access to wav files but the pattern for the MP3 codec has recently expired so now anyone can create MP3 files without having to pay royalties now before we see how to write code to play MP3 files let's put some MP3 files onto our board so first I'm going to open in my circuit Pi volume then open the sounds folder I copied earlier and I'm going to throw away the one.wave file that I was using previously then I'm going to open the sounds folder that I downloaded from the Google Drive earlier in this lesson and I'm going to copy over three MP3 files nice work encouragement one and encouragement two make sure all three of these files end in MP3 you don't want the encouragement files that have wave at the end of them and it's worth noting that all three of these files fit on the Pico after deleting the WAV file the MP3 files are much smaller so here's how we work with MP3 files now just like wav files you may have to resave your MP3 files with a set of parameters to optimize them for playback in circuit python you want to make sure your file is a mono not stereo file your file should be saved between 16 and 44 kilohertz and between 32 kilobits and 128 kilobits per second again those terms might not mean anything to you but the free audacity program has settings for all of this so stereo to Mono can be found in the tracks menu under mix you can set your kilohertz range in the lower left hand corner and the file menu will let you export support as an MP3 in the save dialog box that pops up you can select variable and then set the quality range to between 32 and 128k BPS now back to our code everything that's different from playing back wav files is in a red box instead of importing wave file from audio core we instead import MP3 decoder from audio MP3 now we still need to set up audio out so this code will remain the same and you also need an audio out object and you need a path too but this next slide is different now first we need to create what's called an MP3 decoder object so it's going to take the ones and zeros that we read from our MP3 file and it's going to decode this into something that we can play through our speaker now it actually takes quite a bit of memory to create an MP3 decoder object so instead of creating it every time we call a function to play an MP3 sound we're just going to create this once before our play underscore MP3 function and then whenever we need to play a new file we're just going to go to the decoder that we created and update its file property by opening the file we we want to play then we just call audio.play passing in decoder which now contains the updated file now before we can create an MP3 decoder we actually need to read in an MP3 file so that's why we have these two statements here you can set file name to any file that's inside of your sounds folder and if you didn't want to use two lines you could just put the string directly into file name we're not actually going to play this file at the start of our program but we need it to create the MP3 decoder object which is what we do in this line here now instead of a play underscore sound function we're going to call this play underscore MP3 so again here's where we simply open the file we want to play so we take the file name and then we add this file that we open up to the property of our decoder object then we audio play and what we pass in here is the decoder object and then we have our while audio dot playing pass remember you can swap out pass for any code you want to run while the sound is playing and then to play a file you simply call play underscore MP3 passing in a string with the exact name of the file that you want to play make sure you get the extensionright.mp3 it's really easy to forget if you were working with waves to change this 2.mp3 so now let's head to move and code this up I'll change the comment to read play MP3 files from the Pico and remember in the third line here we're no longer importing WAV file from audio core instead from audio MP3 we import MP3 decoder and note the capitalization then after we create the audio object and we set our path we'll set up our MP3 decoder first I'll say file name equals the string nice Dash work.mp3 that was one of the files that we copied over to our sounds folder then below this I'll read that file in and I'll call it MP3 underscore file setting that equal to open and in between parentheses path plus file name comma and the string RB make sure you close parens I could have put the string nice Dash work.mp3 in here instead of the file name but I think on two lines it's a little more readable then down below we'll create our decoder and we'll call it decoder setting this equal to the class name MP3 decoder note the capitalization and in parentheses to create an object of this class type we're going to pass in this MP3 file that we created up here now we're no longer going to have a play sound function that's what we use to play wave files we're instead going to play MP3 files so why don't we call this play underscore MP3 and this first line is going to change as well so what we're going to do out front is we're going to set decoder dot file so the file property of the decoder that we created above setting that equal to but we'll keep the open path file name RB in here but we'll delete the as WAV file at the end and there's no colon at the end here this just reads in whatever file name we pass in and sticks that into the file property of our decoder now we no longer need this line down here where we converted things to a WAV file so delete that completely and then these three lines down here that are out dented let's highlight them and we'll shift tabs so they're indented decoder.file audio.play and while audio playing should all be in the same indent level and we don't call audio.play on Wave anymore we call audio.play on decoder so that sets up our play underscore MP3 function and we can reuse that whenever we need to play mp3s just make sure you set up a decoder first then in our last line we're not going to call play sound anymore we're going to call play MP3 and we'll be sure to pass in a string for an MP3 file we'll use nice Dash work.mp3 so now let's open the serial monitor click on Save oh it's work I agree with that let's press save again please work circuit pythonista now you know how to play both wav files and MP3 files on your Raspberry Pi Pico I think that leaves you ready for a challenge but you know what before I attempt that challenge I'm going to save this code to my circuit python school folder calling it play MP3 sounds on a Pico then I'll reopen code.pi on my Pico now here's the challenge the challenge is to get code advice from an MP3 file so connect a button to your pico I'll use pin gp15 and each time the button is pressed alternate between playing the files encouragement 1.mp3 and encouragement2.mp3 I know you can do it this isn't a tough one pause give it a shot and let's compare answers so let's head over to moo and I could do this without debouncing but I'm going to go ahead and use debouncing for my button and I'm already importing digital i o I want to make sure that I do that whenever I work with buttons because those are digital input objects I imported this already but I don't think I used it to name my previous code but from Adafruit underscore the bouncer I'm going to import capital B button then I'll write the code to create a debounce button first I set the pin and I'm going to call this button underscore input setting it equal to digitalio dot digital in out with capital D capital I capital O and we're going to pass in between parentheses board.gp15 since that's the pin I'm using for my button signal then on the next line I need to set my button input so that it is an input so this creates a digital in out object on gp15 now I need to tell it to use it as a digital in so I'm going to say button underscore input dot switch underscore 2 underscore input and in between parentheses I need to set my pull-up resistor with digitalio DOT capital P pull dot in an all caps up and now I can create my debounced button so I'm going to call this lowercase b button setting it equal to capital B button which is the button class that I imported from Adafruit debouncer and I'm going to pass in the button underscore input digital input that I just set up with a pull-up resistor so that code creates a digital i o object at gp15 it sets it to be an input device with a pull-up resistor and that object is passed into the button class so it can create a debounce button now that I've got this set up let's head down and create a while true infinite loop with while capital T true colon now remember before you can check the button status you've got to update your button so I'm going to call Button dot update open and close parens then if the button is pressed and we check that on the next line with the statement if button dot pressed colon I'm going to print you pressed me just to make sure that my button is working then if file name double equal sign equals the string encouragement one dot MP3 colon then on the next line I want to set my file name equal to encouragement2.mp3 and else I want to outdent that so it's at the same level as my if statement make sure you got a colon after else file name equals the string encouragement1.mp3 so as I go through this every time the button is pressed if the file name is encouragement 1 Mp3 then I'm going to change the file name to encouragement to otherwise I'm going to set the file to encouragement one then out Dent it at the same level as if and else when that conditional is evaluated after it's done I'm going to play underscore MP3 passing in my file name now in order for this to work we've got to have something in file name but remember we do Define file name up here we start out by putting nice work.mp3 inside of file name you know what we're not even using nice work in this program though so in case I were to delete that from my sound folder I want to make sure that I'm only using file names that are relevant for this project so instead I'm going to initialize the file name variable with encouragement2.mp3 how come well I gotta put something in file name and the first time I go through here and press a button I check to see if the file name is encouraged 1.mp3 and since it's not I head down here to the else Clause I set file name to encouragement one I want to play that file first and so below this I play encouragement 1. mp3 for the next button press the file name is equal to encouragement one dot MP3 so I change it to encouragement 2 and I play encouragement too now I still have this play MP3 nice work down here this line would never get executed because it's outside of the wild true Loop but I want to delete that I don't want that unused code in my program so now let's open up the serial console and save and try out our program code or coding up there is no try oh that sounds like everybody's favorite Green Sage Master Yoda monster I agree code or code not there is no try code monster you have become how cute you are outstanding you're playing MP3 files on your pico you're alternating between two sounds nice work code monster now before we finish up I want to show you one more python technique and that's the ternary operator the ternary operator is going to allow us to take these four lines that I've highlighted here and turn them into just one line and this is how it works a ternary operator has three parts hence the name ternary meaning three but it only returns one value you write it this way the untrue part what you do if an expression is true comes first then you say if the Boolean expression you want to evaluate something that is true or false again if that expression is true you do what's on the left of the if statement but if it's false well the third part of the ternary operator is the else and you write whatever you return if the condition is false so we're going to use this down below to set file name so I'll write the variable file name and I'll set it equal to and while we don't have to write this ternary X expression in between parentheses I think it makes our code a little bit easier to read because we know we've got to evaluate what's between these parentheses and put it inside a file name so for this first part here if the expression we're about to evaluate is true I want to set file name equal to encouragement2.mp3 so I'm just going to copy encouragement2.mp3 and paste it in so that's what file name will be if an expression I'm about to enter is true what's that expression if this guy right here file name double equals encouragement1.mp3 so I'm going to copy this bit in here and paste it in after my if as the Boolean expression you don't want the colon at the end of this though it's all on one line remember a Boolean expression has only two answers true or false if it's true we go to the left if it's false we go to the right so we follow the expression with the keyword else and if it is not true it's false that file name equals encouragement1.mp3 then after the else I want to pass encouragement1.mp3 copy this here paste it after else that's what's going to go into the file name so I'll shrink this down so you can see it on one line the if clause for the if statement is in the center here on the left hand side of the if statement is what we do if it's true we set file name equal to encouragement2.mp3 and on the right side of the if statement after the else is what we do if it's false we'll set file name to encouragement1.mp3 so these four lines are now in a single line statement I'm going to delete these four lines normally I advise students if you have a choice between writing code that's more readable or code that's shorter it's best to make your code more readable but but the ternary operator is pretty common in Python so you should know how to use it and now you do code monster let's open the serial console again and try out our code to make sure everything's working save no errors code or code not there is no try filter code not there is no try you are a code monster oh there is no try the code monster you have skilled you are you're playing MP3s you're playing waves you're working with d bounced buttons you're working with the ternary operator why don't we save this to our circuit python school folder as MP3 from Pico with the bounce button and ternary operator then I can close this up then reload code.pi on my board this way I'll make sure I don't make any changes to the file that I just saved I hope you are feeling like a circuit python Jedi now go use the force to make something awesome
Info
Channel: John Gallaugher
Views: 17,959
Rating: undefined out of 5
Keywords: sound, audio, songs, music, tones, play, wav, mp3, .wav, files, output, speaker, wire, amplifier, python, CircuitPython, Adafruit, Raspberry, Pi, Pico, Pico W, function, routine, subroutine, sub-routine, tutorial, beginner, newbie, friendly, explained, examples, college, university, course, teach, show, parallel, MPR121, adafruit, twelve, 12, pad, capacitive, touch, detect, finger, circuitpython, raspberry pi, pico, pico w, code, easy, debouncing, press, Button, Debounce, Debouncing, while, pass, fun, Buttons, help, understand, multitask, sense
Id: Lwr8LLvLRb8
Channel Id: undefined
Length: 25min 26sec (1526 seconds)
Published: Thu Feb 23 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.