Shop OBEX P1 Docs P2 Docs Learn Events
How to simply generate a "cuckoo" sound? — Parallax Forums

How to simply generate a "cuckoo" sound?

Christof Eb.Christof Eb. Posts: 1,198
edited 2021-07-23 08:36 in Propeller 1

Hi, this is a question for the sound specialists. :smile:
I want to build a cuckoo clock with P1 and Tachyon. A cuckoo clock is a wall clock which opens a little door every full hour. A little bird is visible and "cuckoo" is heard.
Due to memory constrains of P1, I would like to sythesize this sound. (In a former project with a different processor, I used a wav player.) It is somewhat funny, that in German language, the bird sings "Kuckuck", so there is a third "k" in the sound.
So there are two "oo" with different frequencies and one or two or 3 "k" to be generated.

So far I have found this (sorry in German), https://www.phonetik.uni-muenchen.de/studium/skripten/SGL/SGLKap2.html
which seems to indicate, that a "oo" (u) could be generated with a table, that contains the added sine waves of 4 frequencies F0, F1, F2, F3. If I would multiply that with some sort of envelope?

I would be happy and thankful for some hints, how I could achieve this. It would be very interesting, if it could be done in Forth, without using assembler. I think, I can dedicate a cog for the job.
Thanks in advance, Christof

Comments

  • I think that @Ahle2 and @Wuerfel_21 are experts on sound so maybe they could jump in ? Not sure about the Tachyon part, but still may give you some general ideas.

  • This link shows a circuit that is used to generate a cuckoo sound. It consists of a square wave oscillator that generates 667 Hz followed by 545 Hz. The square wave is filtered and white noise is added to make is sound like a cuckoo. Maybe you can write some code for the P1 to simulate something like this.

  • Propeller Tool comes with a VocalTract.spin that is not very good at actually talking, but decently good if you hand-tune a command sequence. It's mostly PASM, but you'd need to translate a couple Spin methods into forth. It's a bit hard to get it to do what you want though. IIRC there's also a line you need to change if you need high glottal pitch.

  • Thank you both for your answers!
    As I was asking for something simple, I will try to emulate the circuit Dave pointed out. Just a single sine plus noise to disguise the vowel + a sequencer with simple envelope. (No "K" at all.) :-)

  • There's usually a chime that accompanies the cuckoo sound:

    https://freesound.org/people/Dean-Raul_DiArchangeli/sounds/462930/

    Were you planning to include that?

    -Phil

  • Yes, Phil, at my former project with wav files I had this chime too. And depending from the time I have a "cock-a-doodle-doo" (very different vowels in German with "Kikeriki") in the morning and a small owl "huhuuh" in the evening. Some ( steamer ships) bell is marking quarter hours.
    Minimum requirement is "Kuckuck."
    Anyway: Any ideas how to synthesize the chime? Simple!
    At the very moment I am able to output a sine wave but it looks as if the sequencer and the generation of the envelope must be done in a second cog, if no assembler is to be used. The update frequency of the DDS is not very high with tachyon.

    Daves link with hardware is very nice for my project, because there are fallbacks: P1 can generate the square wave via counter, the sequencer and the on-off of the envelope via software, while its shaping and the filtering can be done with the circuit. I am not yet sure about the white noise, because I only have 5V.

    This cuckoo clock shall have a different main attraction. It shall be a trip hammer https://en.wikipedia.org/wiki/Trip_hammer with a water wheel. So there will be plenty of noise.... (If I succeed....) I want to drive the mechanics of the hammer with a stepper motor. So the number of hammer blows should be able to be controlled.
    The clock dial shall be represented by a neopixel ring.
    Perhaps some neopixel light effects for the smiths hearth and the waterflow?
    Time shall come from a DCF-77 long wave receiver which has to be decoded.
    Plenty of work for P1...

  • MJBMJB Posts: 1,235

    @"Christof Eb." said:
    This cuckoo clock shall have a different main attraction. It shall be a trip hammer https://en.wikipedia.org/wiki/Trip_hammer with a water wheel. So there will be plenty of noise.... (If I succeed....) I want to drive the mechanics of the hammer with a stepper motor. So the number of hammer blows should be able to be controlled.

    so you can do quarter blows 1 / 2 / 3 / 4 - and then Kuckuck at full clock 1 .. 12 as the hour is (like the original black forest cocoo clock)

  • MJBMJB Posts: 1,235

    Peter provides SIDcog as a COGlet to load into Tachyon.
    Might be overkill to generate a cocoo but if there is a cog free - why not use it?

  • OK, this is the code so far, does not sound too bad:

    \ KuckuckC.fth
    \ Based on http://www.redcircuits.com/Page76.htm
    
    : sine ( n -- sine ) \ n=0...1024
        DUP SWITCH
        0 255 CASES
            4 << $E000 + @ $FFFF AND BREAK 
        0 511 CASES
            512 SWAP - 4 << $E000 + @ $FFFF AND BREAK 
        0 767 CASES
            512 - 4 << $E000 + @ $FFFF AND NEGATE BREAK 
        1024 SWAP - 4 << $E000 + @ $FFFF AND NEGATE 
    ;
    
    64 longs sinetab
    
    : fillsine 
        64 FOR
            I 1024 * 64 / sine 2 / 
            sinetab I 2 << + !
        NEXT
    ;
    
    fillsine
    
    pub DAC16! ( word pin -- )  DUP LOW APIN DUTY 16 <<
    --- Set the value of the current FRQ either A or B
    pub FRQ ( n --  )       FRQA +CTR COG! ;
    
    long freq#  10000 freq# !
    
    long vol# 10 vol# !
    
    long noise# $0700.000 noise# !
    
    : sinout \ DDS on pin 0
        0
        BEGIN 
        freq# @ + 
        DUP 1000 / $FC AND sinetab + @ 
        \ RND noise# @ / + \ add noise costs time
        vol# @ * 150 / 32767 + 0 DAC16!
        AGAIN
    ;
    
    ' sinout 3 RUN
    
    19122 := lowfreq
    
    23401 := highfreq
    
    : kuckuck ( n -- ) \ n=0...1000
        DUP SWITCH
        0 100  CASES highfreq freq# !   vol# ! BREAK
        0 300 CASES DROP BREAK
        0 500 CASES 500 SWAP - 2 / vol# ! BREAK
        0 600 CASES DROP BREAK
        0 700  CASES lowfreq freq# !   600 - vol# ! BREAK  
        0 800 CASES DROP BREAK
        0 1000 CASES 1000 SWAP - 2 / vol# ! BREAK
    ;
    
    : sequ
        1000 FOR 400 us I kuckuck NEXT ;
    
  • MJBMJB Posts: 1,235

    I had no real idea what this SIDcog was about -
    pretty impressing:
    https://youtube.com/watch?v=zgUMfNJieO4

  • Just for fun I converted the program to Spin. It sounded a little distorted with a sample rate of 2.5 KHz, so I increased it to 4.88 KHz. It sounds pretty good. I'm not sure what is required to make it sound more like a real cuckoo clock. It would be interesting to generate the chime, and mix that with the cuckoo sound.

  • I'm not sure what is required to make it sound more like a real cuckoo clock.

    It needs some "breathiness." Cuckoo clocks use bellows-activated whistles, and a lot of the air escapes without being modulated. What results is a flute-like sound with a lot of brown noise.

    -Phil

  • I found the source of the distortion. I was masking the sine table index with $3C instead of $3F. I fixed that and it sounds better now. I also added some noise, but I don't think it improves it much. It's probably because I'm adding white noise instead of band-pass filtered noise. I also had to switch to FlexProp to get higher speed. The Spin bytecode interpreter was a little slow to keep up.

  • Christof Eb.Christof Eb. Posts: 1,198
    edited 2021-07-25 14:38

    Hi, Dave, great!
    Don't you want to build the complete clock now?
    ((The neopixel ring does make a nice clock face, simple to use, if you have a WS2812 driver, and an opening door can be made quiet easily with a servo....))

    I too have had the impression, that adding the "breathiness" noise did not improve the sound. Due to the limited update frequency there seems to be enough noise? I also have the impression, that a real bird does not have that breathiness.

    Perhaps it would be better to have a separate envelope for the noise.
    sound= sine * envelopeA + noise * envelopeB
    It should be possible to "low pass filter the noise" using the same number more than once.

    I ask myself, if something like a chime could be achieved, with this setup too, something like "tshing".

    With the compiler now, you could put the sinvalout loop into the other cog?

    Have fun, Christof

  • MJBMJB Posts: 1,235

    @"Christof Eb." said:
    OK, this is the code so far, does not sound too bad:

    \ KuckuckC.fth
    \ Based on http://www.redcircuits.com/Page76.htm

    sine ( n -- sine ) \ n=0...1024
    DUP SWITCH
    0 255 CASES
    4 << $E000 + @ $FFFF AND BREAK
    0 511 CASES
    512 SWAP - 4 << $E000 + @ $FFFF AND BREAK
    0 767 CASES
    512 - 4 << $E000 + @ $FFFF AND NEGATE BREAK
    1024 SWAP - 4 << $E000 + @ $FFFF AND NEGATE
    ;

    64 longs sinetab

    fillsine
    64 FOR
    I 1024 * 64 / sine 2 /
    sinetab I 2 << + !
    NEXT
    ;

    fillsine

    pub DAC16! ( word pin -- ) DUP LOW APIN DUTY 16 <<
    --- Set the value of the current FRQ either A or B
    pub FRQ ( n -- ) FRQA +CTR COG! ;

    long freq# 10000 freq# !

    long vol# 10 vol# !

    long noise# $0700.000 noise# !

    sinout \ DDS on pin 0
    0
    BEGIN
    freq# @ +
    DUP 1000 / $FC AND sinetab + @
    \ RND noise# @ / + \ add noise costs time
    vol# @ * 150 / 32767 + 0 DAC16!
    AGAIN
    ;

    ' sinout 3 RUN

    19122 := lowfreq

    23401 := highfreq

    kuckuck ( n -- ) \ n=0...1000
    DUP SWITCH
    0 100 CASES highfreq freq# ! vol# ! BREAK
    0 300 CASES DROP BREAK
    0 500 CASES 500 SWAP - 2 / vol# ! BREAK
    0 600 CASES DROP BREAK
    0 700 CASES lowfreq freq# ! 600 - vol# ! BREAK
    0 800 CASES DROP BREAK
    0 1000 CASES 1000 SWAP - 2 / vol# ! BREAK
    ;

    sequ
    1000 FOR 400 us I kuckuck NEXT ;

    those have been in EXTEND in previous versions using the SIN-table in P1 ROM

    pub COS ( angle -- cosine \ the angle is in radians scaled to ?? bits ?? )
    $800 +

    pub SIN ( angle -- sine \ the angle is in radians scaled to ?? bits ?? )
    DUP $1000 AND SWAP \ test quadrant 3|4
    DUP $800 AND IF NEGATE THEN \ test quadrant 2|4 and negate if true
    $7000 OR 2* W@ \ lookup word from sin table
    SWAP IF NEGATE THEN \ if quadrant 3|4, negate sample
    ;

Sign In or Register to comment.