QB64 Phoenix Edition
Speaking and Chiming Analog Clock - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Programs (https://qb64phoenix.com/forum/forumdisplay.php?fid=7)
+---- Thread: Speaking and Chiming Analog Clock (/showthread.php?tid=2931)



Speaking and Chiming Analog Clock - SierraKen - 08-13-2024

This is a fixed and updated version of a clock I made years ago. Before when it spoke "10" it actually said, "one, zero". Did similar with 11 and 12. So I fixed that today and added a digital clock up above the analog clock. Plus I fixed it when it's supposed to say "minute" not "minutes" and "second" and not "seconds". I also added the day of the week and date using the weekday code from my old Calendar making program. If any of you want that again, I can post that also. This clock speaks the date (and weekday) and the time using the Windows Powershell text-to-speech that is built into Windows. This is when we were playing with this back then. I also added the ability to hear it in either male of female voice.
Dav is the one that posted the chimes frequencies and code back then, thanks Dav! 


Code: (Select All)

'Speaking and Chiming Analog Clock by SierraKen
'Updated on August 13, 2024.
'Thanks to Dav for the chiming frequencies and code.

_Title "(N)umerals With or Without, (1) Male Speak, (2) Female Speak,  (Space Bar) Chimes"
Screen _NewImage(600, 600, 32)

rom = 1
Cls
tt = 23
d = 0
Do
    _Limit 100
    For t = 0 To 360 Step .5
        x2 = (Sin(t) * 190) + 300
        y2 = (Cos(t) * 190) + 300
        For sz = .1 To 5 Step .1
            Circle (x2, y2), sz, _RGB32(127, 255, 127)
        Next sz
    Next t

    For t = 1 To 359
        For tt = t - 2 To t + 2 Step .5
            x2 = Int((Sin(tt) * 170) + 300)
            y2 = Int((Cos(tt) * 170) + 300)
            For sz = .1 To 5 Step .1
                Circle (x2, y2), sz, _RGB32(255, 255, 255)
            Next sz
        Next tt
    Next t
    If rom = 0 Then GoTo skip:
    For sc = 1 To 60
        ss = (60 - sc) * 6 + 180
        x4 = Int(Sin(ss / 180 * 3.141592) * 150) + 300
        y4 = Int(Cos(ss / 180 * 3.141592) * 150) + 300
        Circle (x4, y4), 3, _RGB32(230, 230, 230)
        n2 = (60 - sc) * 6 + 180
        x3 = Int(Sin(n2 / 180 * 3.141592) * 140) + 290
        y3 = Int(Cos(n2 / 180 * 3.141592) * 140) + 295
        Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)
        If sc = 5 Then _PrintString (x3, y3), "I"
        If sc = 10 Then _PrintString (x3, y3), "II"
        If sc = 15 Then _PrintString (x3, y3), "III"
        If sc = 20 Then _PrintString (x3, y3), "IV"
        If sc = 25 Then _PrintString (x3, y3), "V"
        If sc = 30 Then _PrintString (x3, y3), "VI"
        If sc = 35 Then _PrintString (x3, y3), "VII"
        If sc = 40 Then _PrintString (x3, y3), "VIII"
        If sc = 45 Then _PrintString (x3, y3), "IX"
        If sc = 50 Then _PrintString (x3, y3), "X"
        If sc = 55 Then _PrintString (x3, y3), "XI"
        If sc = 60 Then _PrintString (x3, y3), "XII"
    Next sc
    skip:
    hours = Timer \ 3600
    minutes = Timer \ 60 - hours * 60
    seconds = (Timer - hours * 3600 - minutes * 60)
    ho$ = Left$(Time$, 2): hou = Val(ho$)
    min$ = Mid$(Time$, 4, 2): minu = Val(min$)
    seco$ = Right$(Time$, 2): secon = Val(seco$)

    pendulum tt, d

    'Minutes
    m = 180 - minutes * 6
    xx = Int(Sin(m / 180 * 3.141592) * 120) + 300
    yy = Int(Cos(m / 180 * 3.141592) * 120) + 304
    For b = -5 To 5 Step .1
        Line (300 + b, 304)-(xx, yy), _RGB32(0, 255, 255)
        Line (300, 304 + b)-(xx, yy), _RGB32(0, 255, 255)
    Next b
    'Hours
    h = 360 - hours * 30 + 180
    xxx = Int(Sin(h / 180 * 3.141592) * 75) + 300
    yyy = Int(Cos(h / 180 * 3.141592) * 75) + 304
    For b = -5 To 5 Step .1
        Line (300 + b, 304)-(xxx, yyy), _RGB32(0, 255, 0)
        Line (300, 304 + b)-(xxx, yyy), _RGB32(0, 255, 0)
    Next b
    'Seconds
    s = (60 - seconds) * 6 + 180
    xxxx = Int(Sin(s / 180 * 3.141592) * 125) + 300
    yyyy = Int(Cos(s / 180 * 3.141592) * 125) + 304
    For b = -5 To 5 Step .1
        Line (300 + b, 304)-(xxxx, yyyy), _RGB32(255, 0, 0)
        Line (300, 304 + b)-(xxxx, yyyy), _RGB32(255, 0, 0)
    Next b
    For sz = .1 To 10 Step .1
        Circle (300, 300), sz, _RGB32(255, 255, 127)
    Next sz

    _Display
    Line (0, 0)-(600, 600), _RGB32(0, 0, 0), BF

    'Chimes
    If (minu = 0 And secon = 0) Or song = 1 Then

        'note frequencies
        For notes = 1 To 20
            If notes = 1 Then note = 311.13 'D#
            If notes = 2 Then note = 246.94 'B
            If notes = 3 Then note = 277.18 'C#
            If notes = 4 Then note = 185.00 'F#
            If notes = 5 Then note = 0
            If notes = 6 Then note = 185.00 'F#
            If notes = 7 Then note = 277.18 'C#
            If notes = 8 Then note = 311.13 'D#
            If notes = 9 Then note = 246.94 'B
            If notes = 10 Then note = 0
            If notes = 11 Then note = 311.13 'D#
            If notes = 12 Then note = 277.18 'C3
            If notes = 13 Then note = 246.94 'B
            If notes = 14 Then note = 185.00 'F#
            If notes = 15 Then note = 0
            If notes = 16 Then note = 185.00 'F#
            If notes = 17 Then note = 277.18 'C#
            If notes = 18 Then note = 311.13 'D#
            If notes = 19 Then note = 246.94 'B
            If notes = 20 Then note = 0

            Do
                'queue some sound
                Do While _SndRawLen < 0.5 'you may wish to adjust this
                    sample = Sin(ttt * note * Atn(1) * 8) '340Hz sine wave (ttt * 440 * 2p)
                    sample = sample * Exp(-ttt * 3) 'fade out eliminates clicks after sound
                    _SndRaw sample
                    ttt = ttt + 1 / _SndRate 'sound card sample frequency determines time
                Loop
                'do other stuff, but it may interrupt sound
            Loop While ttt < 1 'play for 1 second
            Do While _SndRawLen > 0 'Finish any left over queued sound!
            Loop
            ttt = 0
        Next notes
        hour2 = hou
        If hour2 > 12 Then hour2 = hour2 - 12
        If hour2 = 0 Then hour2 = 12
        For chimes = 1 To hour2
            Do
                'queue some sound
                Do While _SndRawLen < 0.1 'you may wish to adjust this
                    sample = Sin(ttt * 240 * Atn(1) * 8) '340Hz sine wave (ttt * 440 * 2p)
                    sample = sample * Exp(-ttt * 3) 'fade out eliminates clicks after sound
                    _SndRaw sample
                    ttt = ttt + 1 / _SndRate 'sound card sample frequency determines time
                Loop
                'do other stuff, but it may interrupt sound
            Loop While ttt < 2 'play for 2 seconds
            Do While _SndRawLen > 0 'Finish any left over queued sound!
            Loop
            ttt = 0
        Next chimes
        song = 0
    End If
    two:
    a$ = InKey$
    If a$ = Chr$(27) Then End
    If a$ = " " Then song = 1
    If a$ = "n" Or a$ = "N" Then
        rom = rom + 1
        If rom > 1 Then rom = 0
        For sz = .1 To 180 Step .1
            Circle (300, 300), sz, _RGB32(0, 0, 0)
        Next sz
    End If
    If a$ = "1" Then speaker = 0
    If a$ = "2" Then speaker = 1
    If a$ = "1" Or a$ = "2" Then
        hour2 = hou
        If hour2 > 11 Then
            ampm$ = "P M"
        Else
            ampm$ = "A M"
        End If
        If hour2 > 12 Then hour2 = hour2 - 12
        hour3$ = Str$(hour2)
        hour4 = Val(hour3$)
        If hour4 = 0 Then hour4 = 12
        hour5$ = Str$(hour4)
        min2 = Val(min$)
        min3$ = Str$(min2)
        seco2 = Val(seco$)
        seco3$ = Str$(seco2)
        hour5$ = _Trim$(hour5$)
        If hour5$ = "10" Then hour5$ = "ten"
        If hour5$ = "11" Then hour5$ = "eleven"
        If hour5$ = "12" Then hour5$ = "twelve"
        If _Trim$(min3$) = "1" Then smin$ = "minute"
        If _Trim$(min3$) <> "1" Then smin$ = "minutes"
        If _Trim$(seco3$) = "1" Then ssec$ = "second"
        If _Trim$(seco3$) <> "1" Then ssec$ = "seconds"
        sentence$ = "Today's date is " + w$ + ", " + month$ + " " + dd$ + ", " + yy$ + ", and the time is " + hour5$ + ampm$ + ", " + min3$ + " " + smin$ + ", and " + seco3$ + " " + ssec$

        speak sentence$, speaker, 0
    End If

    mm$ = Left$(Date$, 2)
    dd$ = Mid$(Date$, 4, 2)
    yy$ = Right$(Date$, 4)
    mm = Val(mm$)
    dd = Val(dd$)
    yy = Val(yy$)
    GetDay mm, dd, yy, weekday

    If weekday = 1 Then w$ = "Sunday"
    If weekday = 2 Then w$ = "Monday"
    If weekday = 3 Then w$ = "Tuesday"
    If weekday = 4 Then w$ = "Wednesday"
    If weekday = 5 Then w$ = "Thursday"
    If weekday = 6 Then w$ = "Friday"
    If weekday = 7 Then w$ = "Saturday"
    If mm = 1 Then month$ = "January"
    If mm = 2 Then month$ = "February"
    If mm = 3 Then month$ = "March"
    If mm = 4 Then month$ = "April"
    If mm = 5 Then month$ = "May"
    If mm = 6 Then month$ = "June"
    If mm = 7 Then month$ = "July"
    If mm = 8 Then month$ = "August"
    If mm = 9 Then month$ = "September"
    If mm = 10 Then month$ = "October"
    If mm = 11 Then month$ = "November"
    If mm = 12 Then month$ = "December"
    hour2 = hou
    If hour2 > 12 Then hour2 = hour2 - 12
    If hour2 = 0 Then hour2 = 12
    hour2$ = Str$(hour2)
    Locate 2, 34: Print hour2$ + ":" + min$ + ":" + seco$
    Locate 4, 27: Print w$ + ", " + month$ + " " + dd$ + ", " + yy$
Loop

End

Sub pendulum (tt, d)
    If d = 0 Then tt = tt + (.26 / 2)
    If d = 1 Then tt = tt - (.26 / 2)
    If tt < 24.25 Then d = 0
    If tt > 26 Then d = 1
    theta = .3 * Cos(Timer)
    x5 = (Sin(theta) * 80) + 300
    y5 = (Cos(theta) * 80) + 300
    For sz = -3 To 4
        Line (300 + sz, 300)-(x5, y5), _RGB32(255, 255, 127)
        Line (300, 300 + sz)-(x5, y5), _RGB32(255, 255, 127)
    Next sz
    For sz = .1 To 15 Step .1
        Circle (x5, y5), sz, _RGB32(255, 255, 127)
    Next sz
    _Delay .06
    _Display
End Sub

Sub speak (text As String, Speaker As Integer, Speed)
    Dim message As String, remove$, out$
    Dim As Long i, j
    message = text
    'some symbols and such can't be used with Powershell like this, as they're command symbols
    'we need to strip them out of our text.  (Like apostrophes!)
    remove$ = "'" + Chr$(34) 'add to remove$ here, if more symbols need to be removed as future testing showcases problems
    For j = 1 To Len(remove$)
        Do
            i = InStr(message, Mid$(remove$, j, 1))
            If i Then message = Left$(message, i - 1) + Mid$(message, i + 1)
        Loop Until i = 0
    Next
    out$ = "Powershell -Command " + Chr$(34)
    out$ = out$ + "Add-Type -AssemblyName System.Speech; "
    out$ = out$ + "$Speech = New-Object System.Speech.Synthesis.SpeechSynthesizer; "
    If Speaker = 0 Then out$ = out$ + "$Speech.SelectVoice('Microsoft David Desktop'); "
    If Speaker = 1 Then out$ = out$ + "$Speech.SelectVoice('Microsoft Zira Desktop'); "
    If Speed Then out$ = out$ + "$Speech.Rate =" + Str$(Speed) + "; "
    out$ = out$ + "$Speech.Speak('" + message + "');" + Chr$(34)
    Shell _Hide out$
End Sub

'This section gets the right weekday.
Sub GetDay (mm, dd, yy, weekday) 'use 4 digit year
    'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
    If mm < 3 Then yy = yy - 1
    If mm < 3 Then mm = mm + 12
    century = yy Mod 100
    zerocentury = yy \ 100
    weekday = (dd + Int(13 * (mm + 1) / 5) + century + Int(century / 4) + Int(zerocentury / 4) + 5 * zerocentury) Mod 7
End Sub