PCM player using SCC

Página 19/33
12 | 13 | 14 | 15 | 16 | 17 | 18 | | 20 | 21 | 22 | 23 | 24

Por ARTRAG

Enlighted (6923)

imagem de ARTRAG

24-10-2007, 17:46

I was thinking to your initial proposal and IMHO
the switch option should be restated in this way:

A = read rotation register
L = read last updated option

M = A*32+L

assume N(M) be the number of samples to be copied when the scc is at position A and the last updated value is L

switch (M) {
case  0: update waves from L up to N(M) wait two samples (15&16) update the remaining 32-N(M) samples
case  1: update waves from L up to N(M) wait two samples (15&16) update the remaining 32-N(M) samples
...
case 1023: update waves from L up to N(M) wait two samples (15&16) update the remaining 32-N(M) samples
}

Apart for the work needed to implement and tune it, is this solving the problem of reading the ch4 while sample 15&16 are played ?
Smile

Less than one read per INT call is impossible.
Having main code synchronized with the PCM player in order to avoid the read in the "critical" period is terrible.

maybe the poliphase approach, even being limited to 7680Hz, could become a real appealing solution for PCM SFX

Por dvik

Prophet (2200)

imagem de dvik

24-10-2007, 19:11

Apart for the work needed to implement and tune it, is this solving the problem of reading the ch4 while sample 15&16 are played ?

No. I don't think its possible to do an implementation that is not fully synchronized to avoid any access while playing sample 15 and 16. This means that its not possible to write an interrupt based replayer. Maybe its possible to reset the sample counter in each interrupt but that probably won't work that well either. The best you can do with that method is probably the demos Manuel posted, but they do suffer from quite a lot of clicks.

Por ARTRAG

Enlighted (6923)

imagem de ARTRAG

24-10-2007, 19:47

Well, reduce the Fs to 11KHz, minimize the transfer time using the tricks on the 32 extra samples in ram or duplicated and pray

If the table update takes 4 samples at 11KHz (my guess, but the new loop is faster)
with 6 HINTS per frame, the probability to hear a "click" in a frame is 6*4/32

maybe the noise is bearable especially if you play music and sfx at the same time...

Por dvik

Prophet (2200)

imagem de dvik

24-10-2007, 20:13

It has nothing to do with how fast the implementation is. The problem is that in an interrupt driven model you can't know what sample you're currently playing when the interrupt starts executing. So you need to do at least one read to Ch4 to see where you're at. This does unfortunately not work because one single read in the wrong way will have very negative impact.

The routine last posted does only read at most once in the wrong place every interrupt (many times its not accessing the SCC in that region at all) but the result is still not good enough.

Reducing the sample frequency doesn't help either.

But as you said, maybe it is bearable. Its not horrible but unfortunately far from as good as it can be. But it is a fairly low impact pcm player so its ideal for a game since it leaves so much of the cpu to other tasks.

Por ARTRAG

Enlighted (6923)

imagem de ARTRAG

24-10-2007, 20:19

maybe the poliphase approach, even being limited to 7680Hz, could become a real appealing solution, at least for human voice and for PCM SFX...
It writes channels only when scc is at the end of thwavetable....

A new challenge?
Wink

Por dvik

Prophet (2200)

imagem de dvik

24-10-2007, 20:41

I don't think the quality will be that good to be honest. It depends a little bit on how often the phase counters need to be reset. Every now and then the phase of the channels need to reset to avoid drifting. If this can be limited to once a second or less I think it may be ok. It will add clicks which will be a bit annoying. Other than that it should be ok.

If you can split a sample into four, the way you described I can do a quick implementation. Btw, how do you get 7680Hz if you only update 4x32 samples every frame? I thought the frequency would be 60*4*4 or something.

Por ARTRAG

Enlighted (6923)

imagem de ARTRAG

24-10-2007, 20:49

The total freq is 4*32*60Hz = 7680 Hz

Actually as the Fs of all channels need to be set to 1920 Hz (take care of the -1 in the period, now it is crucial!!!)
you need to reset and update each waveform at different time in the VBLANK interrupt

ch1 needs to be reset and updated at 0 (asap)
ch2 needs to be reset and updated at 1/7680
ch3 needs to be reset and updated at 2/7680
ch4 needs to be reset and updated at 3/7680

if update and reset can be done within ONE sample time, you'll get max 60 clicks per sec (like a low freq buzz)

I cannot produce data right now... sorry
If you want I'll try in 2-3 days...

Por dvik

Prophet (2200)

imagem de dvik

24-10-2007, 20:55

Problem is that I have plenty of time today but soon I won't have so much time. My office is closed because of the wildfires but when it reopens I need to catch up with what I haven't been doing the last couple of days. I'll find some time but probably not as quick progress as the last couple of days.

Por ARTRAG

Enlighted (6923)

imagem de ARTRAG

24-10-2007, 20:58

this was the final (tested in Matlab) algorithm

Ok, with the correction I did, all the volumes settings in the loop are unnecessary
I think that everything could be restated in this way:

ch1(1) = ph1(1);
ch2(1) = ph2(1) - ch1(1);
ch3(1) = ph3(1) - ch1(1) - ch2(1);
ch4(1) = ph4(1) - ch1(1) - ch2(1) - ch3(1);

for i=2:size(Y)/4
 ch1(i) = ph1(i)-ch2(i-1)-ch3(i-1)-ch4(i-1);
 ch2(i) = ph2(i)-ch1(i)-ch3(i-1)-ch4(i-1);
 ch3(i) = ph3(i)-ch1(i)-ch2(i)-ch4(i-1);
 ch4(i) = ph4(i)-ch1(i)-ch2(i)-ch3(i);
end


where Y is the input, phX is the input subsampled
on phase X and chX is channel X

1) set to zero the wave tables of the 4 channels

loop :

2a) load 32 bytes in ch1
2b) set freq in ch1 => sample 1 is well reproduced as only ch1 is active - in the first iteration -
2c) wait 1/7680 secs (the complement to, in order to keep timing accuracy)

3a) load 32 bytes in ch2
3b) set freq in ch2 => sample 2 should be well reproduced as only ch1&2 are active - in the first iteration -
3c) wait 1/7680 secs (the complement to, in order to keep timing accuracy)

4a) load 32 bytes in ch3
4b) set freq in ch3 => sample 3 should be well reproduced as only ch1,2&3 are active - in the first iteration -
4c) wait 1/7680 secs (the complement to, in order to keep timing accuracy)

5a) load 32 bytes in ch4
5b) set freq in ch4 => sample 4 should be well reproduced as all chs are active 
5c) wait 1/7680 secs (the complement to, in order to keep cycle accuracy)

6) wait (32/1920-4/7680 = 124/7680) secs (the complement to, in order to keep cycle accuracy)

7) goto loop

According to the equations, original samples should be correctly reproduced even after the reproduction of first 4 samples,
and even between two loop iterations (i.e. the output of 32 samples).

Again, if it works standalone as cycle accurate loop, it can go in an interrupt too, 
and in any case, steps from 2a) to 5b) must be cycle accurate even when in interrupts

If it works, the time "wasted" in the int routine is 3/7680 secs, not a lot, without considering that in each pause of 1/7680 secs you can do VDP I/O (you can fit about 25 outi in it)

Por dvik

Prophet (2200)

imagem de dvik

24-10-2007, 21:00

I'll give it a try and see how it goes.

Página 19/33
12 | 13 | 14 | 15 | 16 | 17 | 18 | | 20 | 21 | 22 | 23 | 24