It is currently Mon Nov 20, 2017 5:58 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Sat Aug 19, 2017 5:57 pm 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
Hello friends! Help me with a simple question. I hope it's simple. :roll:

In my game, I use the sound like this:

Code:
  lda #%00000001
   sta $4015 ;square 1
   lda #%01010111
   sta $4000
   lda #$C9
   sta $4002
   lda #$02
   sta $4003


How can I play two sounds one after another?

beep1 -> pause -> beep2

or

Audible sound - inaudible sound - Audible sound, i.e. beep1 -> beep2 -> beep3 (beep 2 -Can not hear)

Help me write the working code. My game lacks only sound. I do not want to use the sound engine, since the game will be minimalistic. :)

ImageImageImage

...thanks! :roll:

_________________
http://famicom.space


Top
 Profile  
 
PostPosted: Sat Aug 19, 2017 6:34 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3484
Location: Indianapolis
Welcome.

I don't think that example will make any sound because the length counter bits (upper 5 bits of $4003) are zero. For a simple beep you could set the length counter and enable it to set how long the beep lasts, then you won't need a second register write to turn the audio off. To make a delay between multiple beeps you need some type of timer.

Here's an example of a really simple sound engine, hopefully no bugs because it's not tested or anything. This shows one way you could start a sequence, handle timing between notes, and have it automatically end (setting the delay value to zero ends the sequence).

Code:
initialize: ; call this once
 lda #%00000001
 sta $4015
 lda #0
 sta sequence
 sta stop_flag
 jsr get_next
 rts

play: ; call this every frame
 lda stop_flag
 bne @do_nothing
 dec timer
 bne @do_nothing
 jsr get_next
@do_nothing:
 rts

get_next:
 ldx sequence
 lda delay_table,x
 beq @end_sequence
 sta timer
 lda table4000,x
 sta $4000
 lda table4001,x
 sta $4001
 lda table4002,x
 sta $4002
 lda table4003,x
 sta $4003

 inc sequence
 rts

@end_sequence:
 lda #1
 sta stop_flag
 rts

@non_zero:


delay_table: .byte 30, 60, 0 ; 30 frames, 60 frames, end
table4000: ; values to write to reg for each beep etc.


Top
 Profile  
 
PostPosted: Sat Aug 19, 2017 6:43 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1824
Location: DIGDUG
Personally, I would set a constant tone, wait a few frames, turn the volume off (LDA #0, STA $4000), wait a few frames, turn the volume on again, wait a few frames, and turn the volume back off.

It could also be done with careful settings of the 'loop' and 'length counter', but it may not sound exactly like what you want, and is very tricky.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Sat Aug 19, 2017 8:45 pm 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
I can not write a working code. Errors ... :(

At the moment the sound works like this:

https://www.youtube.com/embed/77N0uQfCUqQ

I can not write the correct code myself, because any error can be difficult to fix. I'm not a programmer.. :(

_________________
http://famicom.space


Last edited by Guyver on Thu Aug 31, 2017 3:41 am, edited 2 times in total.

Top
 Profile  
 
PostPosted: Mon Aug 21, 2017 12:52 am 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
Code:
Playsound: ;;sound
   lda #$FF
   sta $4000
   lda #%10011010
   sta $4001
   lda #$C5
   sta $4002
   lda #$CB
   sta $4003
   lda #%00000001
   sta $4015
   rts


Timer: ;;delay
     LDA #$FF
     STA $0700
     LDA #0
     STA $0701
 loop:DEC $0700
     BNE loop
     DEC $0701
     BNE loop
 RTS

 jsr Playsound ;;melody
 jsr Timer
 jsr Playsound
 jsr Timer
 jsr Timer
 jsr Playsound
 jsr Timer
 jsr Timer
 jsr Timer
 jsr Playsound

_________________
http://famicom.space


Top
 Profile  
 
PostPosted: Mon Aug 21, 2017 3:00 am 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
Simple song:

Code:
NotaDo:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$F0
   sta $4002
   lda #$00
   sta $4003
   rts

NotaRe:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$D5
   sta $4002
   lda #$00
   sta $4003
   rts

NotaMi:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$BD
   sta $4002
   lda #$00
   sta $4003
   rts

NotaFa:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$B2
   sta $4002
   lda #$00
   sta $4003
   rts

NotaSo:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$A0
   sta $4002
   lda #$00
   sta $4003
   rts

NotaLa:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$90
   sta $4002
   lda #$00
   sta $4003
   rts

NotaSi:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$80
   sta $4002
   lda #$00
   sta $4003
   rts

NotaDo1:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$78
   sta $4002
   lda #$00
   sta $4003
   rts

NotaRe1:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$6C
   sta $4002
   lda #$00
   sta $4003
   rts

NotaLaD:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
                 lda #$87
   sta $4002
   lda #$00
   sta $4003
   rts

NotaStop:
  lda #%00000001
   sta $4015
   lda #%01010111
   sta $4000
                 lda #$00
   sta $4002
   lda #$05
   sta $4003
   rts

Timer:
     LDA #1
     STA $0700
     LDA #0
     STA $0701
 loop:DEC $0700
     BNE loop
     DEC $0701
     BNE loop
 RTS


Code:
 jsr NotaLa ;;classic song
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaFa
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaMi
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaRe
 jsr Timer
 jsr NotaRe
 jsr Timer
 jsr NotaFa
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaRe1
 jsr Timer
 jsr NotaDo1
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaFa
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaMi
 jsr Timer
 jsr NotaDo
 jsr Timer
 jsr NotaMi
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaDo1
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaLaD
 jsr Timer
 jsr NotaLa
 jsr Timer
 jsr NotaSo
 jsr Timer
 jsr NotaFa
 jsr Timer
 jsr NotaMi
 jsr Timer
 jsr NotaRe
 jsr Timer
 jsr NotaStop


Tell me where you can get a table of notes? For a different frequency of sound. I compiled this table myself by ear.

_________________
http://famicom.space


Top
 Profile  
 
PostPosted: Mon Aug 21, 2017 6:30 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19237
Location: NE Indiana, USA (NTSC)
Guyver wrote:
Tell me where you can get a table of notes? For a different frequency of sound. I compiled this table myself by ear.

APU period table has a table and a Python program to generate it.


Top
 Profile  
 
PostPosted: Mon Aug 21, 2017 6:35 am 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
Thanks! :beer:

_________________
http://famicom.space


Top
 Profile  
 
PostPosted: Mon Aug 21, 2017 9:47 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5824
Location: Canada
The next suggestion might be to learn about arrays and iteration. You don't have to copy paste the same code many times with one thing different, you can put the different parameters in a table array), and then write an interative loop to use them one by one. Here's your song rewritten this way:
Code:
; table of pitches
pitch_low:  .byte $F0, $D5, $BD, $B2, $A0, $90, $80, $78, $6C, $87, $00
pitch_high: .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $05

NDO = 0
NRE = 1
NMI = 2
NFA = 3
NSO = 4
NLA = 5
NSI = 6
NDO1 = 7
NRE1 = 8
NLAD = 9
NSTOP = 10

; plays note from X
Nota:
   lda #%00000001
   sta $4015
   lda #%10100111
   sta $4000
   lda pitch_low, X
   sta $4002
   lda pitch_high, X
   sta $4003
   rts

Timer:
   lda #1
   sta $0700
   lda #0
   sta $0701
@loop:
   dec $0700
   bne loop
   dec $0701
   bne @loop
   rts

classic_song:
.byte NLA, NSO, NLA, NFA, NLA, NMI, NLA, NRE
.byte NRE, NFA, NLA, NRE1, NDO1, NLAD, NLA, NSO
.byte NLDA, NLA, NLAD, NSO, NLAD, NFA, NLAD, NMI
.byte NDO, NMI, NSO, NDO1, NLAD, NLA, NSO, NLA
.byte NSO, NLA, NLAD, NLA, NSO, NFA, NMI, NRE
.byte NSTOP

PlaySong:
   ; use Y as index to array classic_song
   ldy #0
@loop:
   ; fetch note from classic_song into X and play it with Nota
   ldx classic_song, Y
   jsr Nota
   jsr Timer
   ; if the last note was NSTOP, finish
   lda #NSTOP
   cmp classic_song, Y
   beq @end
   ; otherwise advance to the next note
   iny
   jmp @loop
@end:
   rts


Top
 Profile  
 
PostPosted: Tue Aug 22, 2017 2:59 am 
Offline
User avatar

Joined: Sat Aug 19, 2017 5:47 pm
Posts: 11
Location: Russia, Sinegorie
Thanks! How can I stop the sound? Turn off all the sound in the game so that when you turn it on - he does not play again?

_________________
http://famicom.space


Top
 Profile  
 
PostPosted: Tue Aug 22, 2017 10:04 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1824
Location: DIGDUG
To silence a sound channel, either volume = 0 or pitch = 0.

LDA #0
STA $4000

Or you could turn off the channel this way...

LDA #0
STA $4015

Edit, pitch of zero won't stop the noise channel. So, volume of zero would be best for that.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Wed Aug 23, 2017 4:42 am 
Offline

Joined: Tue May 28, 2013 5:49 am
Posts: 872
Location: Sweden
Triangle has no volume control though, so it's easiest silenced by setting the Length Counter Halt Flag and clearing the Counter Reload Value (both done in $4008):
Code:
  lda #%10000000
  sta $4008              ;mute Triangle


Unlike the square channels, I don't think the Triangle can be truly silenced by setting pitch to 0. It will produce ultrasonic sounds at pitch values below 2. According to the wiki, Megaman 2 tries to silence the Triangle this way, resulting in a popping sound when an an audible pitch is resumed (heard in Crashman's stage).

DPCM channel seems to be easiest silenced by simply disabling it in $4015. Not sure as I haven't used it in BGM yet.


Top
 Profile  
 
PostPosted: Fri Aug 25, 2017 10:22 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1824
Location: DIGDUG
Thanks Pokun. I've updated my tutorial to say $80 (register $4008) will silence the Triangle Channel.

14. Intro to Sound

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Aug 29, 2017 4:36 am 
Offline

Joined: Tue May 28, 2013 5:49 am
Posts: 872
Location: Sweden
No problem, I think I learned this from the Nerdy Nights sound tutorial.
Also if you don't use the length counter but want to unmute Triangle again, you just write any non-zero value to the Counter Reload Value while keeping the Length Counter Halt Flag set:
Code:
  lda #%10000001
  sta $4008              ;unmute Triangle


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group