Android Example Happy birthday to you (Beep example)

Hi all.
this example play Happy birthday to you music with beep. (Audio librarie)

B4X:
Sub Globals
    Private lNotas As List
    Private lbNotas As Label
    Private tocando As Boolean
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If Not(lNotas.IsInitialized) Then lNotas.Initialize
 
    Activity.LoadLayout("1")

    'PRIMEIRA PARTE
    lNotas.Add(Array(300,528,"PA"))
    lNotas.Add(Array(300,528,"RA"))
    lNotas.Add(Array(500,594,"BENS"))
    lNotas.Add(Array(500,528,"PRA"))
    lNotas.Add(Array(400,704,"VO"))
    lNotas.Add(Array(1400,660,"CE"))
 
    'SEGUNDA PARTE
    lNotas.Add(Array(200,528,"NES"))
    lNotas.Add(Array(200,528,"TA"))
    lNotas.Add(Array(600,594,"DATA"))
    lNotas.Add(Array(600,528,"QUE"))
    lNotas.Add(Array(400,792,"RI"))
    lNotas.Add(Array(1400,704,"DA"))
 
    'TERCEIRA PARTE
    lNotas.Add(Array(200,880,"MUI"))
    lNotas.Add(Array(200,880,"TAS"))
    lNotas.Add(Array(600,1056,"FE"))
    lNotas.Add(Array(400,880,"LI"))
    lNotas.Add(Array(400,704,"CI"))
    lNotas.Add(Array(400,660,"DA"))
    lNotas.Add(Array(1300,594,"DES"))

    'QUARTA PARTE
    lNotas.Add(Array(200,933,"MUITOS"))
    lNotas.Add(Array(200,933,"A"))
    lNotas.Add(Array(600,880,"NOS"))
    lNotas.Add(Array(600,704,"DE"))
    lNotas.Add(Array(600,792,"VI"))
    lNotas.Add(Array(1600,704,"DA"))
 
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub Toca_beeper
    tocando = True
    For i = 0 To lNotas.Size - 1
        Dim value() As Object = lNotas.Get(i)
        lbNotas.Text = value(2)
        Dim b As Beeper
        b.Initialize(value(0), value(1))
        b.Beep
        Sleep(value(0))
        b.Release
    Next
    tocando = False
    lbNotas.Text = ""
End Sub


Sub btTocar_Click
    If Not(tocando) Then
        Toca_beeper
    End If
End Sub


THX
 

Attachments

  • parabens.zip
    217.9 KB · Views: 649
Last edited:

Douglas Farias

Expert
Licensed User
Longtime User
Create a Map that contains the note (as a name) and the frequency instead of having to work with the numbers? Then you can play whatever you want in a simpler way.
i tryed, but in some times, the key are the same, and replace the old
 

udg

Expert
Licensed User
Longtime User
You could have a single array where each "couple" follows the preceding one.
B4X:
Dim TunesArray(50) As String = Array As String(300,528, 300, 528, 500, 594...1600,704) 'if string is what a Beeper expects..

Or even a list from which you read two values at time.
 

hatzisn

Expert
Licensed User
Longtime User
You could have a single array where each "couple" follows the preceding one.
B4X:
Dim TunesArray(50) As String = Array As String(300,528, 300, 528, 500, 594...1600,704) 'if string is what a Beeper expects..

Or even a list from which you read two values at time.

Why not a 2-dimension array?
 
  • Like
Reactions: udg

Erel

B4X founder
Staff member
Licensed User
Longtime User
Why Array As String?

Example one:
B4X:
Sub Process_Globals
   Private Notes As Map
End Sub
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then
       Notes.Initialize
       Notes.Put("PA", Array As Int(300,528))
       Notes.Put("RA", Array As Int(300, 528))
       Notes.Put("BENS", Array As Int(500,594))
       Notes.Put("PRA", Array As Int(500,528))
       Notes.Put("CE", Array As Int(1400,660))
       '...
   End If
   
   Private l As List = Array("PA", "PA", "CE", "BENS")
   For Each note As String In l
       Dim value() As Int = Notes.Get(note)
       Dim b As Beeper
       b.Initialize(value(0), value(1))
       b.Beep
       Sleep(value(0))
       b.Release
   Next

If performance is important then it is better to do it like this:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
       Notes.Initialize
       Notes.Put("PA", CreateBeeper(300,528))
       Notes.Put("RA", CreateBeeper(300, 528))
       Notes.Put("BENS", CreateBeeper(500,594))
       Notes.Put("PRA", CreateBeeper(500,528))
       Notes.Put("CE", CreateBeeper(1400,660))
       '...
   End If
   
   Private l As List = Array("PA", "PA", "CE", "BENS")
   For Each note As String In l
       Dim value() As Object = Notes.Get(note)
       Dim b As Beeper = value(0)
       Dim duration As Int = value(1)
       b.Beep
       Sleep(duration)
   Next
End Sub

Sub CreateBeeper(Duration As Int, Frequency As Int) As Object()
   Dim b As Beeper
   b.Initialize(Duration, Frequency)
   Return Array(b, Duration)
End Sub

In a real app I would have created a custom type to hold the beeper and the duration.
 

hatzisn

Expert
Licensed User
Longtime User
Well Lucas, I suppose because two notes (frequencies) can have two different durations and if it is used as a map with frequencies as keys then you will face two problems:
a) The second note inserted will ovewrite the first
b) If you do not use a list to put a one value map in each position you will not know the sequence of the notes

An alternative solution would be to add a key with the value of "noteX" where X is a number and a corresponding value for this key "{frequency}~{duration}".
 

hatzisn

Expert
Licensed User
Longtime User
With names as keys:
mapNotes.Put("C2", 66) <-- 66 is the frequence
mapNotes.Put("C#2", 70)
mapNotes.Put("D2", 74)

I am sorry Lucas, I misunderstood but at the end we end up in the same result. You have to also think of the duration of the note and the sequence of all the notes which is a one way road to what I wrote in my previous messages (2-dimensional array or list with one value maps or map with "noteX" as key etc).
 

LucaMs

Expert
Licensed User
Longtime User
I am sorry Lucas, I misunderstood but at the end we end up in the same result. You have to also think of the duration of the note and the sequence of all the notes which is a one way road to what I wrote in my previous messages (2-dimensional array or list with one value maps or map with "noteX" as key etc).
Surely it is necessary to think also about the duration of the notes (and of the pauses) but what I meant is: memorize the names of the notes and their frequencies in a map.

Once this is done, you should create other structures and routines, of course.

Moreover, we are not talking about a "professional tool" (at least I'm not talking about it), in which you should at least include musical chords.
 

LucaMs

Expert
Licensed User
Longtime User
B4X:
Sub Process_Globals
   Private mmapNotes As Map ' all available musical notes.

   Type tSongNote(Name As String, Duration As Int)
   Private mlstSong As List ' of type tSongNote.
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   InitNotes(True)
   InitSong
   PlaySong(mlstSong)
End Sub

Sub InitSong
   mlstSong.Initialize
   AddNoteToSong("C4", 200)
   AddNoteToSong("D4", 300)
   AddNoteToSong("E4", 400)
   AddNoteToSong("D4", 300)
   AddNoteToSong("C4", 200)
End Sub

Sub AddNoteToSong(NoteName As String, Duration As Int)
   Dim Note As tSongNote
   Note.Initialize
   Note.Name = NoteName
   Note.Duration = Duration
   mlstSong.Add(Note)
End Sub

Sub PlaySong(Song As List)
   Dim Frq As Int
   Dim Duration As Int
   For Each Note As tSongNote In Song
       Frq = mmapNotes.Get(Note.Name)
       Duration = Note.Duration
       Dim Beep As Beeper
       Beep.Initialize(Duration, Frq)
       Beep.Beep
       Sleep(Duration)
   Next
End Sub

Sub InitNotes(EnglishNotation As Boolean)
   mmapNotes.Initialize
   Dim lstNotes As List
   lstNotes = File.ReadList(File.DirAssets, "MusicalNotes.csv")
   Dim Parts() As String
   Dim Frq As Int
   For Each Note As String In lstNotes
       Parts = Regex.Split(",", Note)
       Frq = Parts(2)
       If EnglishNotation Then
           mmapNotes.Put(Parts(1), Frq)
       Else
           mmapNotes.Put(Parts(0), Frq)
       End If
   Next
   mmapNotes.Put("P", 0) ' Pause
End Sub

[It can be done much better (haste and little interest :))]
 

Attachments

  • musicalnotes.zip
    612 bytes · Views: 473
Last edited:
Top