Main Site Documentation

Generating cool tones using PWM


#1

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:


#2

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

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


#3

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?


#4

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.


#5

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


#6

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.


#7

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


#8

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:


#9

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:


#10

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:)


#11

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.


#12

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,


#13

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.


#14

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);
            }
        }
    }
}


#15

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


#16

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);
        }
    }
}


#17

Your code at work :slight_smile:


#18

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


#19

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


#20

Ah, reminds me of Yarrs Revenge!