Page 1 of 1

C Sound Libraries

Posted: Fri Apr 29, 2011 4:06 pm
by barnsey123
Has anyone got any sound libraries for use in C programs? I'm looking for various sound effects to supplement/replace the ROM routines.
In particular, anything metallic (clash of swords, hammer on anvil? etc)

Any advice would be welcome.

Posted: Fri Apr 29, 2011 6:03 pm
by Dbug
You can try to use the following function:
void w8912(unsigned char reg,unsigned char value);

It's very low level, but with that you have access to all the registers of the sound-chip.

Alternatively, if you have some free memory, and if you can afford to not do anything while a sound is playing, then possibly you could just replay sample sounds, either using 8 bits or 4 bit samples.

As usual, it's a size/cost/quality trade-off :)

Imo, if you have few kilobytes free, sample sounds could be cool, because with that you can even have voices, growls, laughs, etc...

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 7:04 pm
by waskol
OK, this post is a bit old... but

Since a few, I am working about sound effects with Oric, the way they are generated by PING, EXPLODE or SHOOT (Not zap, because, it does not works the same way).

According to Theoric (Special issue, August 1985, page 36/37) , it works as it :

You have a table of 14 bytes at some address.
for PING, it is located at #FAA7( 64167) : 24,0,0,0,0,0,0,62,16,0,0,0,15,0
for SHOOT, at #FABD( 64189) : 0,0,0,0,0,0,15,7,16,16,16,0,8,0
for EXPLODE, at #FAD3( 64211) : 0,0,0,0,0,0,31,7,16,16,16,0,24,0

Whenever you call PING, SHOOT or EXPLODE :
1 ) Register X is loaded with lower order byte of the table starting address
2 ) Register Y is loaded with higher order byte of the table starting address
3) an Oric routine is called, playing the sound with this table.

Calling SHOOT, calls this piece of code

Code: Select all

ldx #$BD
ldy #$FA 
(JSR #FA6C for Oric1)

by trying and guess, luck I discovered a few interesting sound effects :
Electricity : 0,4,0,184,0,3,120,190,12,0,0,0,167,194
Helicopter : 168,191,0,3,184,191,14,0,0,0,167,194,76,176
Engine : 1,5,193,7,7,8,7,8,53,151,47,151,0,152
Inside the cockpit of a plane : 150,0,152,46,4,255,255,112,7,80,0,102,5,65
A plane (turboprop) : 32,2,140,0,5,132,14,136,132,12,140,0,69,173
Helicopter (far away) : 14,136,132,12,140,0,69,173,0,5,208,4,169,192
Forge hammer hitting an anvil : 32,134,250,96,0,0,0,0,0,0,31,7,16,16

all of these have to be a bit cleaned up (it's a non sense to have some data for channel A for instance, but with channel A non-activated)

found on the web, here (another helicopter) :

Found in the Theoric magazine :
PONG : EE 02 00 00 00 00 00 3E 10 00 00 D0 07 00
PCHH: 00 00 00 00 00 00 01 37 10 00 00 D6 0B 00

Now, what is the meaning of each byte of the table ?
Simply, they correspond to the AY-3-8912 registers :
- 0 and 1 : tone (pitch) on channel A (n between 0 and 4096) (12 bits)
- 2 et 3 : tone (pitch) on channel B (between 0 and 4096) (12 bits)
- 4 et 5 : tone (pitch) on channel C (between 0 and 4096) (12 bits)

note:n=real_period/16/T0 (TO=1µS for Oric) or in short Frequency=1MHz/16/n (n=0 acts as n=1)
Possible frequencies are in range from 62500Hz (n=1) down to approx. 15.26Hz (n=4095)

6 : period of the noise generator (between 0 and 31) note: only bits 0 to 4 are used, Frequency=1MHz/16/n (n=0 acts as n=1)

7: Channels activation
bit 0: channel A
bit 1: channel B
bit 2: channel C
bit 3,4 et 5 mixing of the noise into the three primary channels
becarefull: bit=0 means "activated" bit=1 means NOT activated, for the 6 bits
(note: bit 6 is the port A direction and bit 7 the port B direction, not used for sound generation)

8,9,10 --> volume A,B,C (0 to 16)
more precisely :
- bits 0 to 3 (amplitude): maximum amplitude or volume (0 to 15)
- bit 4 (modulation) : 0 -->fixed amplitude 1-->amplitude controlled by B0-B3 and the envelop generator
Note : The volume is non-linear. The "real world" amplitude can be computed like this :

Code: Select all

 real_world_amplitude = max / sqrt(2)^(15-n),
This amplitude corresponds to the voltage output to a speaker. (15 --> max/1, 14 --> max/1.414, 13 --> max/2, etc...)

11 and 12 --> Envelope step frequency - sound duration - (0 to 65535) note:Frequency=1MHz/16/n (n=0 acts as n=1)
Depending on the envelope shape, the volume is incremented from 0 to 15, or decremented from 15 to 0. In either case it takes 16 steps to complete, the completion time for 16 steps is therefore:

Code: Select all

 T = n*256 / 1MHz      ;with n in range 1..65535 (256µs .. 16.7 seconds)
13 --> envelop (0 to 15) note:only bits 0 to 3 are used.
According to wikipedia (french) : bits 0 to 3 permit to control the sound envelop but only 10 are available because only B2 is taken into account when B3 is equal to zero :

Code: Select all

      B3 - Continue
      B2 - Attack
      B1 - Alternate
      B0 - Hold

Code: Select all

Binary  Hex      Shape
 00XX    00h-03h  \_________  (same as 09h)
 01XX    04h-07h  /_________  (same as 0Fh)
 1000    08h      \\\\\\\\\\
 1001    09h      \_________  (volume remains quiet)
 1010    0Ah      \/\/\/\/\/
 1011    0Bh      \"""""""""  (volume remains high)
 1100    0Ch      //////////
 1101    0Dh      /"""""""""  (volume remains high)
 1110    0Eh      /\/\/\/\/\
 1111    0Fh      /_________  (volume remains quiet)
Registers+envelops : ... e%2021.jpg

Pong sample for OSDK :


Code: Select all

#include <lib.h>

void Pong();

void main()
	while(get()!='Q') Pong();

Code: Select all

	.byt 238,2,0,0,0,0,0,62,16,0,0,208,7,0

	ldx #<Pongtable
	ldy #>Pongtable
	jsr $FA86
There's a lot to dig in with this, because it is rather simple to put in practice, it does not consume a lot of memory.
Moreover (I would like to study that closely), it may be interesting to look out around with what can exist for the cpc464, for instance, or other microcomputer, for instance : ... mstrad.htm

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 7:29 pm
by Dbug
I wonder if we can find random sequences of bytes in ROM that would create decent sounds :)

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 9:43 pm
by waskol
My "trying and guess" are coming from this "random " exploration, I used those values :
- for y --> 0
- for x --> 11,12,13, 14 ,23 , 25, 147, 149,154,165,184,185

some interesting sounds too with y=$FA (like for SHOOT, PING EXPLODE), testing x from 0 to 255

Adding the "Anvil/Hammer metallic sound for the final of Oric Kong (when all the metallic structure of the building is falling down) :)

For sure it opens soooooooooooo many possibilities to the Oric World.
I am very surprised that nobody digged that out since 80's

Just for the pleasure to see how it is simple to use it in BASIC too :

Code: Select all

10 FOR X=#400 TO #415 
 40 DATA #A2,#8         'LDX $8 (data file - low) 
 50 DATA #A0,#4         'LDY $4 (data file - high) 
 60 DATA #20,#6C,#FA    'JSR $FA6C (for Atmos replace #6C by #86) 
 70 DATA #60            'RTS 
100 DATA 32,134,250,96,0,0,0,0,0,0,31,7,16,16
120 POKE#26A,11
130 CLS
140 PRINT "Hit the anvil with your hammer by"
145 PRINT "pressing any key !"
150 GET A$
160 CALL#400
170 GOTO 150

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 9:51 pm
by iss
Nice effects and useful too!

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 9:58 pm
by Chema
Someone did: Twilighte, of course. Do you remember this thread? viewtopic.php?f=15&t=516

In fact I used that technique for the sfx in 1337. However, the effects produced this way are quite simple and do not offer many possibilities. I took a totally different path for Oricium, but it is also much more complicated as my engine (it is documented and the sources are in the repo) is used for playing the music too.

A quick note... you can replace the jsr xxxx / rts pair with a jmp xxxx. 1 byte and some cycles are saved this way.

Re: C Sound Libraries

Posted: Tue Oct 09, 2018 10:10 pm
by waskol
Chema wrote:
Tue Oct 09, 2018 9:58 pm
A quick note... you can replace the jsr xxxx / rts pair with a jmp xxxx. 1 byte and some cycles are saved this way.
I was not sure about that, I am a very beginner in machine code.

I was wondering to if there was a possibility to call a C array from a function in order to load the x index and y index with the address in argument, like this :

Code: Select all

unsigned char mysoundfx[14];
looking at the OSDK lib, I see that the y index is already used to load arguments, so I can't figure out how to implement the machine code.
OK, I found another way (see above), but it was a practice question to myself, just wondering how to do it.

Edit : I found a way, but it's ugly (OSDK article about "preprocessor abuse")

Code: Select all

#define soundfx(soundtableadr)  ldx #<soundtableadr:ldy #>soundtableadr:jmp $FA86
Twilighte did ? THE GOD among the Oric world...

PS : between I have edited my preceeding post to show a BASIC (funny if it is) example
PS2 : some more details and clarifications about the registers and envelops in my first post

Re: C Sound Libraries

Posted: Thu Oct 25, 2018 4:14 am
by NekoNoNiaow
Dbug wrote:
Tue Oct 09, 2018 7:29 pm
I wonder if we can find random sequences of bytes in ROM that would create decent sounds :)
I love the idea, it would allow to play nice sounds using only a two bytes index into the corresponding address.

I guess it would be quite easy to write a small C program to incrementally "play" the entire ROM this way, one "sample" every two seconds with a few keyboard commands to pause/rewind/save when an interesting sound is heard. ;)