Generating cool tones using PWM

I know this is very well possible and easy but I am not sure where to start! I have seen someone take MIDI file and play it on the peizo. Now, forget MIDI file…how do i make some cool noises like the old Atari did? IT should be just a sequence of frequencies that you have to feed in to the PWM but what frequencies? Is there some project that I can copy those sequences from?

The support guy is asking fro support! It is your chance to help back :smiley:

Here is an URL for musical notes versus frequencies. Does this help?

[url]http://www.phy.mtu.edu/~suits/notefreqs.html[/url]

no because I do not want to play songs, I would just use MIDI for that. I want to generate cool noises, like the ones you hear in old arcade games. Like how do you make an explosion sound from a peizo? or a whistle?

Ah… I think most of the early games had multi-channel sound chips. I think you might be able to generate sounds with hugh OutputCompare arrays…

There are a lot of sites on the web that have audio clips for various Atari sounds. I think the easiest way would be to find mp3 sound clips and use the mp3 extension.

And we have multi channel PWM :slight_smile: I am not looking for anything fancy. Any cool noise that can be made with a peizo is cool

Maybe use a raw 32Khz .WAV file to get the PCM code and then feed the PWM with that. You may need a small amplifier eg. LM3xx and a 2nd order filter if the 8Khz buzz is present.

I thought that you can vary the duty cycles on the PWM outputs but the clock is the same for all.

In trying this I got a noise generator.


             for (int i = 0; i < 5; i++)
            {
                Utility.Piezo(400, 100);
                Utility.Piezo(500, 100);
                Utility.Piezo(600, 100);
                Utility.Piezo(700, 100);
            }
            for (int i = 0; i < 20; i++)
            {
                Utility.Piezo(800, 100);
                Utility.Piezo(400, 100);
            }

One can play around with the frequency and duration to produce a lot of tones.

I am having fun :slight_smile:

Here is some sort of a siren on a dying power supply.


            for (uint i = 0; i < 100; i++)
            {
                Utility.Piezo((i * 20), 50);
            }

            for (uint i = 100; i > 10; i--)
            {
                Utility.Piezo((i * 20), 50);
            }


If your dog howls - dont blame me :slight_smile:

Thanks Raj, this is what I usually do. I actually have this already on the LED arcade we made. I was trying to see if there is something that would make better sounds.

I will still try your sequences. It maybe sound cooler than what I have:)

You could use these frequencies to produce some musical notes. However since the parameter to the Utility.Piezo method is unit we have to truncate the decimal part.

I’m working on a project intended to post on the NMF project page.
using a piezo with two 10K variable pots, and three LEDs.

Here is the code which is still preliminary or work in progress.

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;


/* 
 * Program to play a scale of note from c d e f g a b C
 * The calculation of the tone is made using this math formular
 * 
 *      Time High = 1/(2 * Tone Frequency) = Period / 2;
 * 
 * where: the different tones are described as in the following table:
 * Note     Freq.in Hz  Period      PW(Time High)
 * c        261         3830        1915
 * d        294         3400        1700
 * e        329         3038        1519
 * f        349         2864        1432 
 * g        392         2550        1275
 * a        440         2272        1136
 * b        493         2028        1014
 * C        523         1912        956
 * 
 * (cleft) 2005 D. Cuartielles for K3
 * */

namespace FEZ_Domino_Application1
{
    public class Program
    {
        static int valP01 = 0;
        static int valP02 = 0;

        static int Rval = 0;
        static int Gval = 0;
        static int Bval = 0;

        static PWM R_LED = new PWM((PWM.Pin)FEZ_Pin.PWM.Di9);
        static PWM G_LED = new PWM((PWM.Pin)FEZ_Pin.PWM.Di6);
        static PWM B_LED = new PWM((PWM.Pin)FEZ_Pin.PWM.Di5);

        static int[] tones = new int[]{ 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };

        static int toneVal = 0;


        public static void color2RGB(byte val)
        {
            if (val > 252)
                val = 252;
            byte hd = (byte)(val / 42);
            byte hi = (byte)(hd % 6);
            byte f = (byte)(val % 42);
            byte fs = (byte)(f * 6);

            switch (hi)
            {
                case 0:
                    Rval = 252; Gval = fs; Bval = 0;
                    break;
                case 1:
                    Rval = 252 - fs; Gval = 252; Bval = 0;
                    break;
                case 2:
                    Rval = 0; Gval = 252; Bval = fs;
                    break;
                case 3:
                    Rval = 0; Gval = 252 - fs; Bval = 252;
                    break;
                case 4:
                    Rval = fs; Gval = 0; Bval = 252;
                    break;
                case 5:
                    Rval = 252; Gval = 0; Bval = 252 - fs;
                    break;

            }
            // Noe since we have the common-anode Tricolor LED,
            // we need to do "255 - pinValue"
            R_LED.Set(10000, (byte)(((255 - Rval) * 100) / 255));
            G_LED.Set(10000, (byte)(((255 - Gval) * 100) / 255));
            B_LED.Set(10000, (byte)(((255 - Bval) * 100) / 255));

            toneVal = (hi * 8) / 6;
        }

        public static void rgbOut(int val)
        {
            // divide the potentiometer value (0-255)
            // into eight parts 255 ' 8 = 32
            // into three, lowest, middle , and highest
            // lowest third, 255 / 8 = 85

            if (val < 32) // 0 - 85
            {
                Rval = 255 - (val * 8) ;
                Gval = 1;
                Bval = (val * 8);
            }
            // 
            else if (val < 64) 
            {
                Rval = 1;
                Gval = ((val - 64) * 8);
                Bval = 255 - ((val - 64) * 8);
            }
            else  if(val < 72)
            {
                Rval = ((val - 72) * 8);
                Gval = 255 - ((val - 72) * 8);
                Bval = 1;
            }


            // Noe since we have the common-anode Tricolor LED,
            // we need to do "255 - pinValue"
            R_LED.Set(10000, (byte)(((255 - Rval) * 100) / 255));
            G_LED.Set(10000, (byte)(((255 - Gval) * 100) / 255));
            B_LED.Set(10000, (byte)(((255 - Bval) * 100) / 255));
        }

        public static void Main()
        {
            AnalogIn Pot01, Pot02;

            FEZ_Components.Piezo myPiezo = new FEZ_Components.Piezo(FEZ_Pin.PWM.Di10);

            Pot01 = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An0);
            Pot01.SetLinearScale(0, 256);

            Pot02 = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An2);
            Pot02.SetLinearScale(0, 256);

            while (true)
            {
                valP01 = Pot01.Read();

                color2RGB((byte)valP01);

                myPiezo.Play(tones[toneVal], 1000);
                Thread.Sleep(100);

            }
        }

    }
}

And here is the diagram.
All of the components used in this project is from available components here.
Included the Piezo driver.

Enjoy,

How fast can the Analog Output ports be set? If you modulate the PWM with the Analog Output via a NPN transistor you might be able to do AM and FM modulation and get explosions.

So I managed to hook up one of the PWM to the Collector input of an NPN transistor, the base to the analog output, and a speaker to the emitter. The speaker then connects to ground. Using the following code I managed to get some “explosion” like sounds from the AMThread. The FMThread produces weird computer sounds.

using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.Hardware;
using System.Threading;
using GHIElectronics.NETMF.FEZ;

namespace Fez_Music
{
    public class Program
    {
        
         
        public static void Main()
        {
            Thread _amThread = new Thread(AMThread);
            Thread _fmThread = new Thread(FMThread);
            //_fmThread.Start();
            _amThread.Start();
            Thread.Sleep(Timeout.Infinite);
        }

        private static void FMThread()
        {
            PWM _fmPort = new PWM(PWM.Pin.PWM5);
            uint _nanoSecond = 1000000000;
            int _frequency = 0; //in hertz
            float _hertz = 0;
            Random _random = new Random();

            while (true)
            {
                _frequency = _random.Next(200) + 1000;
                _hertz = (float)1 / (float)_frequency;
                _fmPort.SetPulse((uint)(_hertz * _nanoSecond), (uint)((_hertz / 2) * _nanoSecond));

                Thread.Sleep(_random.Next(100) + 100);
            }
        }

        private static void AMThread()
        {
            AnalogOut _amPort = new AnalogOut((AnalogOut.Pin)FEZ_Pin.AnalogOut.A3);
            _amPort.SetLinearScale(0, 3301);

            Random _random = new Random();
            while (true)
            {
                _amPort.Set(_random.Next(2000) + 1000);
                Thread.Sleep(1);
            }
        }
    }
}

analog+PWM … nice idea! I didn’t think of that!

I connected the speaker between ground and PWM5, wrote this program. Now it sounds more like atari video games now.

using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.Hardware;
using System.Threading;
using GHIElectronics.NETMF.FEZ;

namespace Fez_Music
{
    public class Program
    {
        static PWM _fmPort = new PWM(PWM.Pin.PWM5);
        static uint _nanoSecond = 1000000000;
        public static void Main()
        {
            float C = 16.35F;
            float D = 18.35F;
            float E = 20.6F;
            float F = 21.83F;
            float G = 24.5F;
            float A = 27.5F;
            float B = 30.87F;

            _fmPort.Set(false);
            ///Attempt to play The Musical Scale
            int _scale = 10;
            int _duration = 5;
            while (_scale < 50)
            {
                PlayNote(C, _scale, _duration); //C
                PlayNote(D, _scale, _duration); //D
                PlayNote(E, _scale, _duration); //E
                PlayNote(F, _scale, _duration); //F
                PlayNote(G, _scale, _duration); //G
                PlayNote(A, _scale, _duration);//A
                PlayNote(B, _scale, _duration);//B
                _scale++;
                _duration++;
            }
            while (_scale > 5)
            {
                PlayNote(C, _scale, _duration); //C
                PlayNote(D, _scale, _duration); //D
                PlayNote(E, _scale, _duration); //E
                PlayNote(F, _scale, _duration); //F
                PlayNote(G, _scale, _duration); //G
                PlayNote(A, _scale, _duration);//A
                PlayNote(B, _scale, _duration);//B
                _scale--;
                _duration--;
            }
            _fmPort.Set(false);
        }
        /// <summary>
        /// Plays a note on the speaker
        /// </summary>
        /// <param name="frequency">Frequency of the Note</param>
        /// <param name="duration">Duration of the note</param>
        private static void PlayNote(float frequency, int scale, int duration)
        {
            float _hertz = 0;
            _hertz = (float)1 / ((float)frequency * scale);
            _fmPort.SetPulse((uint)(_hertz * _nanoSecond), (uint)((_hertz / 2) * _nanoSecond));
            Thread.Sleep(duration);
            _fmPort.Set(false);
        }
    }
}

Your code at work :slight_smile:

At first I thought it is sound of modem dial-up …lol so funny!

Hahahah indeed, and afterwards it sounded like a feedback :smiley:

Ah, reminds me of Yarrs Revenge!