Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

8 bit mario coin sound effect on PIC?

Status
Not open for further replies.

Triode

Well-Known Member
I'm thinking of making a project that I would like to put a mario coin sound effect into, the kind from the 8 bit games, like super mario 3 on the NES. I know one option is a voice recording chip, but those are kind of expensive and complicated and it seems like it could be overkill since I'm trying to make a single sound effect that was done with an 8 bit processor in the first place. I have a wide variety of pic16F chips. I've done all kinds of control stuff with them but I've never done sound. Using a pic instead of an audio chip is also attractive because I already need to include the support components for a PIC.

This seems like something that would have been done before, but i didn't find much on google. Does anyone know of an example project where an PIC was used for 8 bit game sounds?
 
Mike, that really seems like overkill, If I were going to use an audio chip I think I would use one thats around $10 like the APR9600.

Nigel's suggestion seems to go in the right direction. My guess is that the mario coin sound effect, that is, the one it plays when you collect a coin, consists of only two tones, one that seems monitonic, then a falling tone. I'm not sure if that one can do the falling tone, but it might be a good basis to do it.

edit, after listening to the sound again, its just two tones, it doesnt really fall, so this could be really easy.
 
Last edited:
Oh, I was saying that the sound module Mike2545 reccomended was overkill. The one Nigel suggested was great for this, what I need to do should be simpler, but thats a good start. Thanks for your link too. I should have what I need to do this.
 
Last edited:
Most of those early game sounds were done with square waves and VERY simple functions in asm on very limited hardware.

Usually the functions just had 2 variables, period and number of repeats. Between the 2 vars you get a beep freq and length.

Then most of the "classic" sounds had a 3rd variable that just changed the period each repeat. So they made the freq ramp up or down during the sound (after every period it adds or subtracts a constant value from the period). If you remember Space invaders or Galaga etc you can recreate all those sounds very easily.

What I would do is load the sound you have into a wave editing program and look at basically what it is doing, then recreate it in software just as a square wave made of periods.
 
Looks like were on the same page, thats just what I was doing.
**broken link removed**
As you can see it consists of two tones, which I could do very easily, but the second tone steps down linearly in volume, I'm not sure how to do that without using the encoder method. I tried the encoded and it works, but it introduces a lot of very high pitch squealing sounds that kind of ruin the effect. So I guess I need to either figure out a way to remove that squaling or a way to do the same pitch with lower volume with a simple square wave.

In case anyone wants to know the X axis is in seconds and the Y axis is the proportion of the output range for this sound format.
 
Last edited:
Hi Triode, that is the "envelope" of the sound and shows the obvious "zones" of each stage of the sound. Each zone looks to be about 60mS.

Now you know what the envelope is doing, you need to zoom in on the timescale so you can see the frequency within each zone. I'm assuming each of those 60mS zones is at a fixed frequency although they are probably different frequencies.

You can make the amplitude change much easier than you may have realised, still using a squarewave. It was common to change the duty cycle, so for the loudest sound you use a duty cycle of about 50/50. Then a really quiet sound may have a duty cycle of 1:99 or so. This was either filtered by a simple RC filter or by the natural filtering from the audio output and speaker.

I'd really like to see what the wave looks like inside each zone. And if you wanted to recreate the sound with squarewaves you could probably compile a list of the 14 or so zones, saying what freq and amplitude each zone is. Then it should be pretty easy to recreate.

Do you have a .wav file of the sound?
 
I didn't think about duty cycle for some reason. I was considering making a D/A converter with resistors in series across several output pins but changing the duty cycle would be much simpler. I zoomed in and counted, it looks like the first tone is around 1000Hz and the second is around 1333Hz.
 
I tested it with audacity and generating those tones sounds right. So heres the technical description of the sound

1000 Hz for 0.08 seconds, constant 100% volume
1333 Hz for 0.80 seconds, linear fade from 100% to 0%

The odd thing is I cant get the tones right. I'm trying to start out with the 1000hz tone so I made this code:

Code:
//configure internal oscilator, watch dog off, low voltage protection off
 #pragma config OSC = INTIO2, WDT = OFF, LVP = OFF
 #include <p18f1320.h>
 //#include <delays.h>
 //#include<timers.h>

//setup pins for LED control
#define SoundPin LATBbits.LATB4
#define SoundTris TRISBbits.TRISB4

unsigned int soundPeriod = 40;
unsigned int freq = 1000;//in hz
unsigned int volume = 50;//in percent

unsigned int counter1 = 0;
unsigned int counter2 = 0;


//set up interrupt
void low_ISR(void);//prototype
#pragma code low_vector = 0x08 //0X08 IS LOW 0X18 IS HIGH
void low_interrupt (void){
_asm goto low_ISR _endasm
}
#pragma code
#pragma interrupt low_ISR


void main(void)
{	
	 // speed up the clock to 8MHz, 18F1320
    OSCCONbits.IRCF0=1;   
    OSCCONbits.IRCF1=1;
    OSCCONbits.IRCF2=1;

	//timer setup
	INTCONbits.GIE = 1; //enable global interupts
	INTCONbits.PEIE = 1; //enable periferial interrupts
	IPR1bits.TMR2IP = 0; //low priority
	PIE1bits.TMR2IE = 1; //enable timer 2
	
	//Timer2 Registers Prescaler= 4 - TMR2 PostScaler = 2 - PR2 = 1 - Freq = 250000.00 Hz - Period = 0.000004 seconds
	T2CON |= 8;        // bits 6-3 Post scaler 1:1 thru 1:16
	T2CONbits.TMR2ON = 1;  // bit 2 turn timer2 on;
	T2CONbits.T2CKPS1 = 0; // bits 1-0  Prescaler Rate Select bits
	T2CONbits.T2CKPS0 = 1;
	PR2 = 1;         // PR2 (Timer2 Match value)

	soundPeriod = 250;
	
	SoundTris = 0;
	SoundPin = 1;
	while(1){}
}

void low_ISR(void)
{		

	//Timer 2 flag interrupts at 250000.00 Hz
	if(PIR1bits.TMR2IF)
	{
		PIR1bits.TMR2IF = 0; //clears the timer 1 interupt flag
		counter1++;
		
		if(counter1 > soundPeriod)
		{
			counter1 = 1;
		}

		
		if(counter1 > soundPeriod/2)
		{
			SoundPin = 1;
		}
		else
		{
			SoundPin = 0;
		}
		
	}

}

I figured since that interrupt speed should give me 250khz, if I divide by 250 like that I should get 1khz, but it is much lower than that. I'm going to try a frequency test on it and see what it works out to.
 
With the internal clock at 8MHz and an interrupt at 250kHz you only get 8 instructions between interrupts. Your interrupt is definitely longer than 8 instructions. Just the context save and restore will be too long.

BTW, the NES had a dedicated computer for the sound (plug in module). The main processor was a 6502 and the sound processor was a Sony proprietary one (SPC700) that was similar to a 6502.

Mike.
 
I've been trying different speeds and hitting that limitation. Attempting to make the volume cut down over time keeps making the sound go slower because it doesn't have time to process the instructions, but if i set the interrupt slower there is less resolution to change the volume and pitch. Using the math you showed (I was unaware that 8mhz gives you 200K instructions per second) I figured that for this specific purpose, a 1Khz and a 1.33Khz tone, I could go as low as a 4khz interrupt, but I need enough interrupts to be able to fade the volume at least 10 times so the jump doesn't make it sound bumpy.

I see what you mean, the 6502 is sold as a pinball machine part on several sites, and it looks like with one instruction you can just set the sound module oscillating or change it's pitch and volume. If I needed to do a lot of sounds, or really had to do this one that would be the way to go. It's still a good thing to know about.

For now I think I just need to learn more efficient coding, I'm actually looking at the times instructions take, which I know professionals do a lot, but it's new to me. I am a professional, just at mechanical engineering, not embedded programming.

Also, Mr. RB, I tried your encoder and it's very easy to use, but do you know of any existing code to play the output on a pic within a C18 or PICC program? I see that it can output assembly or binary but I don't really know how to efficiently read those to turn a port on and off.
 
Last edited:
Why not calculate the output required at 20kHz and output that. Even top end Audio stuff doesn't work at 250kHz.

Mike.
 
I was trying it at 40Khz, but you're right, even 20khz would be plenty, 4Khz obviously wasn't enough because it leaves no room to vary the volume.
 
Hi Triode, you really don't need an interrupt to create that sound, unless you need to be doing other things during the 800mS the sound is playing.

I would suggest making a simple function that makes a tone for 60mS duration (as per each little "zone" of your sound.

That function will have 2 variables;
1. freq (just use a timing or count variable)
2. duty cycle

Then just call that function 14 times telling it which freq and duty you need for each zone. Job done. :)

If you want even greater simplicity you can just use 2 variables;
1. HI period
2. LO period

This will be very easy to code as a function and you can specify duty cycle and freq from the periods selected.

If you do that, a function to generate the 60mS tone would look something like this (apologies for hasty typed psuedo code);
Code:
// makes tone 1kHz, 5% duty cycle
  HI_period = 5;
  LO_period = 95;
  call make_tone;


make_tone
  clrf TMR0      ; used to detect end of 60mS
make_tone_HI
  bsf PORTB,0    ; output pin HI
  call delay_10uS
  decfsz HI_period
  goto make_tone_HI
make_tone_LO
  bcf PORTB,0    ; output pin LO
  call delay_10uS
  decfsz LO_period
  goto make_tone_LO
  if TMR0<60mS goto make_tone_HI 
  return
 
Hello Triode! RB!

I'm also interested in having this accomplished.

At home a have and old VW bug horn as my door bell. I needed it *really* loud after my parents were outside my house about 15 minutes waiting for someone to notice them.

Now I don't need all that noise but still amazes my visitors. Now I want to have a 'Mario coin' door bell. I have one 8 bit MCU from Microchip in my 'electronics bin' and I would like to do this circuit.

The original Nintendo system had 5 audio channels. It is very well documented: 2 Square Wave variable duty cicle, One Triangle Wave, One 'White Noise' output and one Sample Output.

For most of my needs I just need the PWM, the Triangle and the Noise generator.

First to generate the square tone the MCU I have includes a PCM generator that is ideal to use for the pulse output.
Second the triangle or ramp wave can be generated using 4 bit outputs from the MCU and a simple DAC converter.
Third channel is the White Noise that can be generated as the original Nintendo did with a linear feedback shift register or with a bad quality diode by taking the thermal noise and feeding an amplifier.

All three channels will be mixed at a buffer stage that will deliver the audio signal. This buffer stage is the same as the DAC at a fixed level. So this will take several weeks as I have only a couple hours a week to spend on this hobby.

Triode, did you made any progress on this?
 
To get the exact sound, you can get the Turbo Pascal source code of the Mario clone for MS-DOS here

https://www.wieringsoftware.nl/mario/source.html

The source code was released by Mike Wiering, the original author of the MS-DOS Mario clone. I played it on my 386 Tandy years ago.

Look for the MUSIC.PAS file - inside that there are Pascal procedures to generate sound for various Mario actions - including "coins" effects. All of them are just using a PC speaker, so i guess should be replicable on a PIC.
 
Hello mdanh2002 .. Yes! A new comer just revived this old thread. Thanks for the Pascal Code. It would help me to get other sounds. I was able to reproduce the sound with the information Triode posted and it is very close to what I need. I added some 'tune' effect. I want this to be my door bell. Yesterday I diged for my stuff from the old days. Project board, components, wires, PS, solder and a Microchip 8 bit MCU with PWM output I have lying in my room for about 3 years. I'm missing a small speaker but I got one speaker from and old car. And yes, lots of power transistors.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top