Is there a way to playTone with two or more frequencies at the same time?

I'm just starting out with Connect IQ and thought this might be something cool to try. I've created app watch project targeting the Fenix 6 series and started out practicing with playTone. Since you can create arrays of ToneProfile entries and play them in succession, I decided to try and play a chord. I've tried a few things, neither have quite worked.

Idea 1: Call playTone twice.

var concertC = 
[			        
    new Attention.ToneProfile(523, 1000)
];

var concertG = 
[			        
    new Attention.ToneProfile(784, 1000)
];

Attention.playTone({:toneProfile=>concertC});
Attention.playTone({:toneProfile=>concertG});

If you do this, the second playTone call "wins". You never hear the first. So this is some sort of async operation where as soon as playTone is called, execution continues, and any subsequent playTone call takes over.

My next tactic was to see if I could play a few tones in quick succession using an array. Maybe we can fool the human ear by playing a little bit of each note back-to-back, so fast that it blends together to us?

public function playCMajor(milliseconds as Integer) {
	var toneProfile = 
	[			        
        new Attention.ToneProfile( 523, milliseconds),
        new Attention.ToneProfile( 659, milliseconds),
        new Attention.ToneProfile( 784, milliseconds),
	];
	
	Attention.playTone({:toneProfile=>toneProfile});
}

In this code example I only add three new ToneProfiles, but in practice I added maybe 100. I called this method with different lengths... 20ms, 10ms, 5 ms, etc. At 20ms, it sounds like a musical trill. At 10ms and at 5ms it starts to sound like buzzing. You can hear the notes... but there's other artifacts in the sound that are lower pitch that start to take over. Does not sound good.

I've tested this in the Simulator on Windows and on my watch. It actually sounds much better on the watch than in the simulator, but still doesn't sound good.

If we can figure this out, my next step would be to try and write and play a short song with chords. Why? Well, why not?

  • Hey,
    thanx for your testing and posting.
    So, it does'nt exist a solution to play two tones in one time?
    I need this function to play DTMF tones.
    Your second way, I have already program a very short melody for a audio transmit code to remotely control my underwater lamp. I have used five pitches with 30ms lenghth and a pause for minimum 30 ms between the pitches, and this works... and sounds not bad
    (apps.garmin.com/.../3d4e48a5-ef94-4125-a647-8b78ce11f3bf).

    Sorry for my bad english.

    When anywho have an idea, how I can play two tones in one moment, so please, please send the solution.

    Thanx very much, René

  • 30 years ago I did something like this. The way to do it is to calculate the sound that is the sum of the two. It gets trickier when different length are also involved. I don't remember the equations, but I'm sure you can easily find it online. So when you want to play frequency F1 and F2 at the same time, instead you play F3 = frequencyAdd(F1, F2)

  • "

    y = A1 sin(2πf1t + φ1) + A2 sin(2πf2t + φ2)

    where y is the resulting wave, A1 and A2 are the amplitudes of the individual waves, f1, and f2 are their frequencies, t is time, and φ1 and φ2 are their phase angles.

    "

    Actually in most cases adding two frequencies will produce complex signal, 3 resulting frequencies. There is no simple way to calculate frequency F3 for F1 + F2.

  • Thanx very much, Bodya.
    Yes, I think also. I am more a Hardware-Engineer as a Software-Enguneer. DTMF-Decoders need really two tones in one time to recognize a valid signal. Maybe it is possible to simulate two tones but it needs a very fast engine to calculate the polyphone tone in each very short moment of the signal.
    The only way, to program two tones ist with a software engine that can produce a run of two functions at the same time ( I think the name of that, is called "threads".
    René

  • I'm not an expert on this platform, but if I remember correctly, the environment that Garmin provides to app developers doesn't provide threads in the traditional computer programming sense. You cannot fork two threads that operate independently and share access to the hardware. Similarly, there isn't an audio mixer available.

    Instead, everything that is available on Garmin watches is through their APIs. It's possible there's some undocumented functionality, but most likely the only supported options are what the API docs list out.

  • I assume these devices are simply using pulse width modulation to create a square wave roughly the frequency that we provide.

    On a device where we have exact control over the output (like a microprocessor) theoretically we could run the math, develop an approximation of the wave function, and develop what the period for two combined tones would look like as zeros and ones. It amounts to a logical OR.

    If there was a way to play that - that'd be super cool. But as far as I know Garmin only provides the playTone function, and it expects a frequency and a duration. A single period of A440 is just over 2 milliseconds. 1 millisecond on high, one millisecond low.

    I don't think the playTone function and what I assume is PWM driving the sound is capable of that. I think we'd need more precision than milliseconds to add two waves together.

    I originally posted this problem two years ago, but it makes me wonder now what would happen if one called playTone, and each entry in the toneProfile were 1 millisecond in duration... any low value provided would amount to a 0, but is there a value that would start out as 1, and could that be used to create the output of the wave function, to essentially write the target square wave that roughly matched the combination of two tones... worth an experiment to see how it might sound.

  • Yes, semi parallel code execution named Threads in many programming languages and paradigms. 
    It is not available on CIQ yet.

    Typically playing two or more tones (signals) in the same time is hardware function.

    I have no idea for audio output architecture available for CIQ app via playTone. As usual Garmin keeps internal implementation hidden,

    What is the shorter duration what can be played via playTone?

  • I have thinking in very similar way. But as I have no ideas where I can play with sounds so I didn't perform any deep research what is possible with CIQ in this area.

    What is the shorter duration what can be played via playTone?

    Also, could you point me on idea why developers want to play complex signals via tiny watch speaker?

  • Can't check your app as it not available for me (probably cos of country or language settings).
    Could you tell me more what is idea? What is hardware underwater? How far watch can be from sensor to activate functions? Thank you a lot!

  • Experimenting with playTone in simulator.

    Sometimes got error in the simulator: 

    Failed to load sound from "/var/folders/08/f8b6fwr12vl7z87ykh5_by600000gn/T/com.garmin.connectiq/GARMIN.wav" (error -1500).

    Examined this folder and have found GARMIN.wav file that sounds as last played tune via Attention.playTone.

    Interesting...not sure on the real devices system creates a file (or chunk in memory) in some wave form according to array of ToneProfile.