0

In order to play a note, we need to know its frequency and how long it should play. To do this, in exercise I have the following two variables:

A dictionary called freqs where the keys are strings representing a character name and the values ​​are numbers representing frequencies.

freqs = {"la": 220,
         "si": 247,
         "do": 261,
         "re": 293,
         "mi": 329,
         "fa": 349,
         "sun": 392,
         }

And strings that include the song notes:

notes =
"sol,250-mi,250-mi,500-fa,250-re,250-re,500-do,250-re,250-mi,250-fa,250-sol,250-sol,250-sol,500"

The strings are constructed as follows:

A comma appears after each character, followed by a number representing the length of time the character should play. Each character is separated from one another by a dash. in the first stage I used the split method to split the character strings by the hyphen. And I checked that it was iterable

In order to play a character, I'm supposed to use a skeleton  Next code:

import winsound
...
winsound.Beep (frequency, duration)

When the Beep function receives two parameters: the frequency of a character and the length of time to be played. (duration, frequency)

I need to write a program that plays the song "Little Jonathan" according to the string of notes in the notes (which signifies the structure of the song) to create iterable from the above character strings and run it for loop, or use the next function.

That's my code so far, didn't work well. How do I proceed from here?

def Beep(frequency, duration ):

    for word in duration:
          yield frequency[word]

frequency={"la": 220,"si": 247,"do": 261,"re": 293,"mi": 329,"fa": 
           349,"sol": 392,
          }

res = Beep(['sol,250', 'mi,250', 'mi,500', 'fa,250', 're,250', 're,500', 'do,250', 're,250', 'mi,250', 'fa,250', 'sol,250', 'sol,250', 'sol,500'],frequency)


print(next(res))

the desired output :

250,392  
500,329  
250,349  
250,293  
500,293  
250,261  
250,293  
250,329  
250,349  
250,392 
250,392 
500,392 
  • Your `Beep` function expects `frequency, duration` but you seem to be passing it `song_string, frequency_lookup_table`? – Dan Jan 07 '20 at 14:30
  • song_string ? i don't have that value.... – אמילי עמית Jan 07 '20 at 14:31
  • 1
    What is `solar` in the notes? – Gábor Erdős Jan 07 '20 at 14:33
  • 1
    what is `solar` ? – alec_djinn Jan 07 '20 at 14:33
  • As in a string containing the song, I see you called it `notes`. Also, I see you have manually broken it into a list. I think that `Beep` should accept something more like a single note so like this `Beep(293, 500)`. Your task is to convert the string `notes` to ` list to pass iteratively into `Beep`. – Dan Jan 07 '20 at 14:33
  • 1
    Looks like you are calling the function `Beep` with the arguments in inverted order. You have defined it `Beep(dict, list)` but you call it as `Beep(list, dict)` – alec_djinn Jan 07 '20 at 14:36
  • I fixed it, I had spelling errors, that's the SOL character – אמילי עמית Jan 07 '20 at 14:37
  • It seems to me that I did not properly explain my problem with the exercise, I need to run an iterator to run on notes that the song's character name and take from the dict the same values of the characters so that I also have the frequency – אמילי עמית Jan 07 '20 at 14:41
  • 2
    It is not clear if you are using your own Beep function or the one from the library. Why do you define yours? – alec_djinn Jan 07 '20 at 14:49

3 Answers3

2

Beep expects a single frequency and duration of that frequency.

You need to beep for every note in the notestring. Thus you need to iterate trough the notes in a way you can use the frequency and duration of said note. Asuming you have filled 1 array with notes and 1 array with durations you can do this

for note, duration in zip(notes, durations):
    winsound.Beep(freqs[note], duration)

If you have not yet split the string you can iterate over the split result of the string.

for note in notes.split('-'):
   winsound.Beep(freqs(note.split(',')[1], note.split(',')[0])
  • I think you have swapped `-` and `,` in your splitting. The notes are `-` separated, each note is a comma separated pair of frequency,duration. – Dan Jan 07 '20 at 15:17
  • 1
    Hi Dan, thanks for pointing out the mistake. The notes string was a bit confusing in the original post. I have edited the answer, Cheers ! – Samuel Middendorp Jan 08 '20 at 09:52
1

First, let's get your tables correctly.

notes = "sol,250-mi,250-mi,500-fa,250-re,250-re,500-do,250-re,250-mi,250-fa,250-sol,250-sol,250-sol,500"

song = []
for block in notes.split('-'):
    note, duration = block.split(',')
    song.append((note, int(duration)))

Then the function. I assume you are using winsound.Beep() and you want a function that call Beep for each note:duration pair in your song. If so, the following function will do the job.

def play(song):
    freq_table = {
        "la": 220,
        "si": 247,
        "do": 261,
        "re": 293,
        "mi": 329,
        "fa": 349,
        "sol": 392,
    }
    for note, duration in song:
        frequency = freq_table[note]
        print(frequency, duration)
        winsound.Beep(frequency, duration)

play(song)
alec_djinn
  • 10,104
  • 8
  • 46
  • 71
0

There a lot of strange stuff in your notes variable, so i will assume its a typo, and it is indeed in the format of note-duration separated by coma and space.

In that case this should work:

for i in notes.split(", "):
    winsound.Beep(freqs[i.split("-")[1]], i.split("-")[0])
Gábor Erdős
  • 3,599
  • 4
  • 24
  • 56