News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Devilmarkus

Amstrad SSA-1 Speech Synthesizer ROM needed

Started by Devilmarkus, 22:50, 04 January 10

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

gerald

Quote from: nocash on 23:22, 13 January 10
Is yours really doing LoadDeQuest, not LoadReQuest? ;-)
As long as it is not LoadHollyQuest  ;)

Quote from: nocash on 23:22, 13 January 10
> LDQn timing can be limited to a constant delay from the write to FBEE.
Not sure that's required at all... is there any software that relies on the presence of that delay (when detecting the speech chip or so)?
I do not that any sw relies on a delay, but if you set it to none, sw may run differently on emulator than on reald HW.
Remember that LRQ  :P high indicates that you should not load a new allophone. If you test your code to program the SPO on an emulator that do not deal with that delay, you may conclude that you can send 2 allophones in sequence before having to check for that LRQ bit, which is wrong !

Quote from: nocash on 23:22, 13 January 10
> SBY duration is, as expected, function of the allophone (not in the table).
> But the duration of the same allophone is not constant, variation is +/-
> 33% for the shortest (P0) to less that 1% for the longest.
Interesting. Maybe the sp0256 executes delays (with repeat count=1) when it's in standby mode...
With a real SSA1 you will hear it ;). If you do not send a pause at the end of a word, you have a endless and constant sound getting out.  The pause is specified in the SPO256 datasheet.
That effect may be a bit tricky to emulate as you have to loop the end of your sample.

Quote from: nocash on 23:22, 13 January 10
> From an emulation point of view :
> LDQn timing can be limited to a constant delay from the write to FBEE.
> SBY timing could be based on the duration of ... the allophone.
Yup, of course applies only in your test case (where you didn't load extra data into fifo during speech output). In reality, that case won't happen unless the speech software is crappy and causes buffer underruns (some SSA-1 programs actually do that since they check only SBY, others are better, and do check LRQ instead).
The test was done on purpose : get the minimum LRQ high time. The next serie of test will do the same sequence of allophone with a pause pushed on the FIFO. I expect the second LRQ time to be as long as the allophone SBY time minus the pause LRQ time.

Quote from: nocash on 23:22, 13 January 10
> What also need to be checked is what the SPO256 does when allophone
> are written when LDQn is high. Is the new one ignored or does it replace
> the one in the buffer?
Would be interesting to know. And should be easy to test, just write OY-OY-SH shortly after another, and hear what it says.
That the plan, but using some pause instead of sound.

Devilmarkus

Really some detailled infos. I will try if I can use them in my emulation.
Big thanks for testing!!!

BTW.: I also improved the digiblaster emulation (Sounds a bit smoother now)

http://www.youtube.com/watch?v=sMNmr-oVE54
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Ygdrazil

Yeah really great with all the new stuff emulated

BTW.. The white lines in the border (Of the video that shows in the digiblaster playing stuff) is this showing how much 'frametime' it takes to play the samples?

/Ygdrazil

Quote from: Devilmarkus on 11:31, 14 January 10
Really some detailled infos. I will try if I can use them in my emulation.
Big thanks for testing!!!

BTW.: I also improved the digiblaster emulation (Sounds a bit smoother now)

http://www.youtube.com/watch?v=sMNmr-oVE54

nocash

Hi Gerald, you've also measured some allophone times, didn't you? The timings I've currently described in
  http://cpcwiki.eu/index.php/SP0256_Voice_Generator
are "guessed" (there was no info on them anywhere, so I just tried to make sense of various info fragments) (the main guess is "256" which looks nice, but it might be also an odd number like "217" or so).

For allophones 00h..04h, the repeat counts are 1,4,7,15,31 (with pause 64x timing). And for 05h its repeat = 3+3+1+3+1+4+2+4+2+9 = 32 (with 91x pitch timing). So if my guess was correct, the timings should be:
  00h PA1 --> 1*5.251ms    = 5.251ms
  01h PA2 --> 4*5.251ms    = 21.004ms
  02h PA3 --> 7*5.251ms    = 36.757ms
  03h PA4 --> 15*5.251ms   = 78.765ms
  04h PA5 --> 31*5.251ms   = 162.781ms
  05h OY  --> 32*7.466ms   = 238.912ms
is that close to what happens on real hardware? The datasheet gives other values, 10ms, 30ms, 50ms, 100ms, 200ms, and 420ms.

nocash

> If you test your code to program the SPO on an emulator that
> do not deal with that delay, you may conclude that you can
> send 2 allophones in sequence before having to check for that LRQ
Yeah, right, but I'll ignore that case in my emu. If somebody is stupid enough not to check LRQ isn't my fault :-) and if somebody is really trying to do that: it won't work anyways (as soon as sending more than 2 in sequence).

> With a real SSA1 you will hear it . If you do not send a pause
> at the end of a word, you have a endless and constant sound
> getting out.
Yup, I know. At the moment, on cpcwiki it's only described as part of the RET opcode description (the first place where emulator programmers would look for it). For cpc/z80/basic programmers it should be probably also mentioned in section where describing the CPC I/O ports. Or best, at the bottom of the allophone list.

> That effect may be a bit tricky to emulate as you have to loop
> the end of your sample.
What sample? :-) I am emulating the opcodes, so it works automatically without problems.

Devilmarkus

#80
Well, I am using an array for each allophone length:
    public static int lengths[] = {10 ,30 ,40 ,100,200,420,260,70 ,120,210,
                                   140,140,70 ,140,170,70 ,180,100,290,250,
                                   280,70 ,100,100,100,180,120,130,80 ,180,
                                   100,260,370,160,140,190,80 ,160,190,120,
                                   150,190,160,210,220,110,180,360,200,130,
                                   190,160,300,240,240,90 ,190,180,330,290,
                                   350,40 ,190,50 ,0,0,0,0,0,0,0,0,0,0,0,0};


Taken from SPO256 documentation... All times are milliseconds.
But I don't know actually how to use them in a good way...

BTW.: I uploaded all SPO256 allophones as WAV files here!!!
(For JavaCPC I am using the same files but 16bit)

Who is interested:
SPO256-AL2 emulator
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

nocash

#81
> Well, I am using an array for each allophone length:
> Taken from SPO256 documentation... All times are milliseconds.
Hello? You said that you don't emulate the real microprocessor and its repeat counts at all - so, how can you even THINK of using real timings for unreal sounds?

Or did you use corrupt wav files? And need to clip them to real length? I remember seeing such files a year ago, where the recorded files had random length (being longer than the normal allophones).

Devilmarkus

The WAV files I am using are not corrupt.
I need these times to add to a counter to manipulate LRQ/SBY values.
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

nocash

Oh god. The purpose of the LRQ/SBY stuff is to allow to synchronize the software with the duration of the allophones. If you emulate your allophones by using WAV files, then the duration is - precisely - the length of the WAV file.

nocash

Just tested the RSX driver cassette for the SSA-1. The funny part is that it accidently used port FAEE instead FBEE :-) It's loading BC=FBEE, and does then execute OUTI

nice try, but OUTI pre-decements B, so writes to FAEE. of course both works since A8 isn't decoded. It may just increase clashes with other hardware, and won't work on emulators that fully decode FBEE.

robcfg

Quote from: nocash on 16:37, 14 January 10
Oh god. The purpose of the LRQ/SBY stuff is to allow to synchronize the software with the duration of the allophones. If you emulate your allophones by using WAV files, then the duration is - precisely - the length of the WAV file.

And also allows playing with different sets of wav files, just for fun or to emulate the external rom capability of the SP0256.

Devilmarkus

When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Devilmarkus

I need exact timings, because if i don't have them the port write cannot feed the voice data.
I am building a longgggg bytearray by adding all WAV coming from write port.
So that's why I need to improve timings.
DK'Tronics is much easier to handle here.

After the 7th day god decided to sleep...
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

arnoldemu

Quote from: Devilmarkus on 17:12, 14 January 10
I need exact timings, because if i don't have them the port write cannot feed the voice data.
I am building a longgggg bytearray by adding all WAV coming from write port.
So that's why I need to improve timings.
DK'Tronics is much easier to handle here.

After the 7th day god decided to sleep...
I think everyone is free to implement the dk'tronics speech and ssa-1 speech hardware as they wish. If they want to use samples.. fine. if they want to use bullshit samples... fine. if they want to emulate spo exactly then fine.

For the first version of my emulation I too will use samples.

I think the javacpc emulation has helped us to look into the details of this hardware furthur and to experience the speech in games that maybe we didn't know had them.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

gerald

Quote from: nocash on 13:02, 14 January 10
Hi Gerald, you've also measured some allophone times, didn't you?
Yes, you will find them in the attached file. Note this file contains min/avg/max value observed for 10 samples of each allophone

gerald

Quote from: Devilmarkus on 17:12, 14 January 10
I need exact timings, because if i don't have them the port write cannot feed the voice data.
I am building a longgggg bytearray by adding all WAV coming from write port.
So that's why I need to improve timings.
Have you measured how long your wav are for each allophone? I think this should be the better way to get the SBY timing in your case.
You may also want to compare them with the table I've posted and check how close they are with the 'real' value. If your wav are too long they may contain some garbage.


gerald

Quote from: gerald on 21:07, 13 January 10
What also need to be checked is what the SPO256 does when allophone are written when LDQn is high. Is the new one ignored or does it replace the one in the buffer?
And the winner is ...



... the last allophone written in the buffer is played when the current one is finished.

nocash

> Yes, you will find them in the attached file. Note this file contains
> min/avg/max value observed for 10 samples of each allophone
> SPO256_AllophoneLenght.txt

Cool. Thanks!
Hmmmmmm, the timings seem to be almost exactly 1.25 times longer than my calculated timings. So my calculation formula seems to have been correct, except for needing to multiply the result by 1.25.

Any idea where that 1.25 value comes from?

Your 3.12MHz resonator IS running at 3.12MHz, isn't it? I guess that components have some tolerance higher than quartz oscillators, though if it runs only at (3.12/1.25)MHz then it'd be a really high tolerance :-/

And otherwise, if it is 3.12MHz... as far as I know, it uses 7bit PWM output, so the sample rate should be 3.12MHz/128, or half of it, 3.12MHz/256... btw. did you check that, too? With a oscilloscope the PWM pulses should be well visible.



gerald

Quote from: nocash on 20:46, 14 January 10
Hmmmmmm, the timings seem to be almost exactly 1.25 times longer than my calculated timings. So my calculation formula seems to have been correct, except for needing to multiply the result by 1.25.

Any idea where that 1.25 value comes from?

A division by 8 somewhere ? 1/8 = 0.125  ;D

Quote from: nocash on 20:46, 14 January 10
Your 3.12MHz resonator IS running at 3.12MHz, isn't it? I guess that components have some tolerance higher than quartz oscillators, though if it runs only at (3.12/1.25)MHz then it'd be a really high tolerance :-/
My simple multimeter tells me it's running at 3.12MHz. While it is not highly precise, I do not think the multimeter and the oscillator are 25% off  :o

Quote from: nocash on 20:46, 14 January 10
And otherwise, if it is 3.12MHz... as far as I know, it uses 7bit PWM output, so the sample rate should be 3.12MHz/128, or half of it, 3.12MHz/256... btw. did you check that, too? With a oscilloscope the PWM pulses should be well visible.
Using the logic analyser, I measured a 40.25KHz frequency at the DIGITAL OUT pin while no speech (constant square signal). But during speech, the frequency seem to slightly change. I'll try to get a scope to check that waveform.
How to get the 40.25KHz from 3.12MHz is an other mystery, but not important for emulation.

nocash

>> Any idea where that 1.25 value comes from?
> A division by 8 somewhere ? 1/8 = 0.125
I'd be glad if it'd be a 2^n thing. But to be 1.25 times slower that expected... it'd mean to be 5/4 times slower (or 4/5 times faster, if you turn it around).

> My simple multimeter tells me it's running at 3.12MHz.
Okay, then that wasn't the reason. :-/ Would have to good to be true.

> Using the logic analyser, I measured a 40.25KHz frequency at the DIGITAL
> OUT pin while no speech (constant square signal).
Square wave makes sense. If it's silent, PWM should be 50% high, 50% low.

> But during speech, the frequency seem to slightly change.
Maybe the analyser just missed "pulses" at times when PWM is 100% high, 0% low for max amplitude (and vice versa for min). Or there's something more strange going on.

> How to get the 40.25KHz from 3.12MHz is an other mystery, but not
> important for emulation.
Yeah. The how/why part is maybe not so important. Would be nice to know though... getting back to the "divide by five" in the above 4/5 times faster idea...
  3.12MHz/5/16 = 39kHz
Well.... that'be almost, but not really 40.25kHz :-/
Uh, and if they output 7bit PWM samples at 40.25kHz, then the PWM stuff must be running 128 times higher, at 5.152MHz. How strange...

Anyways, knowing about the 40.25KHz frequency is important and helpful (many thanks finding that value) for low level emulation of the voice generator.

nocash

#95
Tried to make some sense of the frequencies...

The older SP0250 application manual describes DAC OUTPUT as 10KHz 7bit PWM. And the newer SP0256 datasheet BLOCK DIAGRAM says 7bit PWM, too. As well as 5KHz max pitch, which means 10KHz sample rate, too.

Let's assume that the datasheet values are correct. Then it'd need the PWM driven at 128x10KHz = 1.28MHz. That would be 3.12MHz/13/3*16. Which is more or less reasonably possible. The divider/multiplier isn't making it a simple "straight" timing design. The reason for doing that was maybe that they needed the 3.12MHz for clocking the filter multipliers internally.

And the 40.25KHz. Let's say there was some inaccuracy caused by the resonator or so, and it should be 40KHz, which would 4x higher than the 10KHz sample rate.

The reason there would be producing the 10KHz sample rate's "silence" as two 50% HIGH/LOW pulses would result in a nasty 10KHz noise. Now, rearranging it to eight 12.5% HIGH/LOW pulses would give much better silence with in-audible 40KHz noise, and which'd be the frequency you've measured.

I think that could/should be how it really works. For emulating it, 10KHz would be the important value, the one at which the pitch/noise/filter stuff is running.

PS: For curiosity, I've uploaded all known sp025x related datasheets at,
  http://cpcwiki.eu/index.php/SP0256

PPS: The differences between the specified & measured allophone times are funny. I had calculated only a few by hand, and figured out that there would be some values wrong in the datasheet. But I didn't expect that almost all values were totally wrong :-)

arnoldemu

Quote from: gerald on 19:40, 14 January 10
And the winner is ...



... the last allophone written in the buffer is played when the current one is finished.
Gerald thankyou for your testing.

Would you be able to show a chronogram or oscilloscope output of the LRQ and SBY signals.. especially the sequence:

inactive -> load allophone -> speaking allophone -> stopped speaking.

I think it would be interesting to see that.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

gerald

Here you are :
The first capture show the whole sequence for the shortest pause.

The second capture detail the beginning of the sequence.


For the 'precise' timing please refer to the previous post ;)

gerald

Hi nocash

Thanks for uploading the datasheets.

Here is a capture of the digital output (pin 24). With persistence over all allophones we can see resolution of the PWM output.




  • each small step is about 635ns -> this is 2 period of 3.12MHz
  • one period is about 24.8us -> this is 40 steps -> 80 period of 3.12MHz
  • The duty cycle is not 50%, the falling edge in 'idle' position is at 17 step
  • signal variation is +/- 16 step around idle position

The PWM seems to have 5bit resolution, but can have 33 different values (-16 to +16)  :o

The position of the next rising edge is also interesting : it can be on step earlier or one step after the one in 'idle' state.

As a side note, the rom clock (pin 26) is 1.56Mhz

nocash

> Here is a capture of the digital output (pin 24). With persistence over
> all allophones we can see resolution of the PWM output.

Cool! Looks a bit other than expected at first glance...

So they have inserted some dummy bits with constant LOW level between the PWM packets. Getting them the desired 10kHz sample rate, by simply using 3.12MHz/2 (instead of my 3.12MHz/39*16 idea, of which the *16 looked a bit overcomplicated anyways).

> one period is about 24.8us -> this is 40 steps -> 80 period of 3.12MHz
I think its 39 steps (+/-1 step, depending on when the next PWM packet starts). Uploaded an edited copy of your image here,
  http://cpcwiki.eu/index.php/SP0256_Measured_Timings
the additional blue digits (1..39) may be helpful to count the steps.
I've also added some notes any my interpretation (which is hopefully correct).

> The position of the next rising edge is also interesting : it can be on
> step earlier or one step after the one in 'idle' state.
Strange :-) really don't want to know why.

Another new thing is that I let my sp0256 emu write the number of 10kHz samples per allophone to a log file (based on the pitch/repeat values in the ROM). Those "calculated" timings are also here:
  http://cpcwiki.eu/index.php/SP0256_Measured_Timings
they do match up perfectly with your measured values, except yours are slightly longer, probably caused by the chip executing "NOPs" in standby mode.

Oh, and here is a -AL2 disassembly that I've found somewhere in the net,
  http://cpcwiki.eu/imgs/2/28/SP0256-AL2-Disassembly.txt

Powered by SMFPacks Menu Editor Mod