CPCWiki forum

General Category => Programming => Topic started by: Shining on 17:25, 22 February 19

Title: Sample-Playback on Plus-DMA question
Post by: Shining on 17:25, 22 February 19

Currently I'm a little bit playing with the plus and I want to output a sample by using the dma.

I've done the following:

- exported a sample (8kHz) unsing audacity->Export Audio->Other uncompressed files->RAW(header-less)->Signed (8-bit PCM)
- wrote a little programm which converts the 8-bit values to 4-bit, using the table which was generated from this example: http://cpctech.cpc-live.com/source/sampplay.html (http://cpctech.cpc-live.com/source/sampplay.html)

- Put the sample into a cartridge-page

Now on Plus:

- Begin at adress 0x4000 (RAM is mapped)
- write 3f, 06 ( mixer register, disable tone and noise)
- Write sample-byte, write 0x08 ( volume register channel A) and so on for all sample bytes
- after the last sample-bytes write 0x20 0x40 (STOP Stop processing the sound list)

- Now I write 0x4000 to 0x6c00,0x6c01 (Channel 0 address), a 0x01 to the Channel 0 prescaler (8 kHz) and 0x01 to 0x6C0F (Channel 0) enable (IRQs are off, DI)

- Now I hear something but it sounds only like noise and it seems to correctly stop at my 0x4020-command and disables the DMA then.



At the moment, I've no clou what I've done wrong. My first guess is, that I've done something wrong with the sample.
Any ideas ?





my table:
{
            0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c
          , 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c
          , 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c
          , 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c
          , 0x0c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d
          , 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d
          , 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d
          , 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d
          , 0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e
          , 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e
          , 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e
          , 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e
          , 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e
          , 0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x0f
          , 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
          , 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
          , 0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03
          , 0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05
          , 0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06
          , 0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07
          , 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07
          , 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
          , 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
          , 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09
          , 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09
          , 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09
          , 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
          , 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
          , 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b
          , 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b
          , 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b
          , 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b
};
Title: Re: Sample-Playback on Plus-DMA question
Post by: TotO on 17:39, 22 February 19
Probably I do not answer to your question... But as I know, the AY sample replay have to be logarithmic (not linear) and the best result is by using values from 0 to 13 only.

Title: Re: Sample-Playback on Plus-DMA question
Post by: roudoudou on 21:16, 22 February 19
Nah
Best result with dynamic compression, disregarding the AY range AND frequency replay
http://memoryfull.net/articles.php?id=4
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 22:52, 22 February 19
Hi,
try with the file attached - if your routine will play it correctly then your sample conversion is broken somewhere.
Btw: I've just noticed that in my sample player the sample is converted with the attached  conversion table. Just read sample byte and get an offset from the table using sample byte value.
Title: Re: Sample-Playback on Plus-DMA question
Post by: Shining on 23:04, 22 February 19
Quote from: Docent on 22:52, 22 February 19
Hi,
try with the file attached - if your routine will play it correctly then your sample conversion is broken somewhere.


Since the bytes in this file contain data greater than 0x0F, are these 8-bit samples? Or did you pack two 4-bit samples into one byte ?



Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 23:17, 22 February 19
Quote from: Shining on 23:04, 22 February 19

Since the bytes in this file contain data greater than 0x0F, are these 8-bit samples? Or did you pack two 4-bit samples into one byte ?
Heh, its actually an 8bit sample that I convert on the fly to the required values with the simple table during refilling of audio dma buffer. Not that very space efficient, but hey, it was a test if I can play some star wars voices on Amstrad :)
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 00:25, 23 February 19
Quote from: Shining on 17:25, 22 February 19

Currently I'm a little bit playing with the plus and I want to output a sample by using the dma.

I've done the following:

- exported a sample (8kHz) unsing audacity->Export Audio->Other uncompressed files->RAW(header-less)->Signed (8-bit PCM)
The best results I got with converting to 16000 Hz and saving as unsigned 8bit PCM. This is the setup I used for saving the sample I attached earlier.

Title: Re: Sample-Playback on Plus-DMA question
Post by: mr_lou on 07:26, 23 February 19
Are there any 3-channel Amiga MOD => Amstrad Plus DMA conversion tools and players around?
Title: Re: Sample-Playback on Plus-DMA question
Post by: Shining on 10:10, 23 February 19
Not that I'm aware of. I did quite some research to find some examples or even some players but there are not that many informations out there. Overflow did something like 3-Channel mod on Shadow of the Beast, but if there are some infos or howtos out there, I don't know. At the moment I'm not behind something like that, only playing one (long) sample for a little project but I'm really interested to have a player for "normal" music, like a plus-player for arkos-tracker 2.
Title: Re: Sample-Playback on Plus-DMA question
Post by: Targhan on 20:22, 24 February 19
I wrote the article Roudoudou linked. 16khz sample is overkill, don't bother (16khz REPLAY is a good idea though). Compress/saturate your sound like hell. Like I told in the article, you can use Sox to convert your samples. You can also export samples using Arkos Tracker 2 "export samples" option, which can export in 4 bits. If you edit each sample, you can use the "volume ratio" option to saturate it at will, it will be exported this way. Getting your sample right is tricky, and require trial-and-error. Subtle samples will simply never sound right on CPC. But crunchy bass and brutal drums often sounds great!

If you are unsure how DMA works, try first to play a sample in "the CPC old way", as documented in the article. DMA will "only" play the samples automatically (which is great if you want to do something else besides playing samples, in a demo or a game for example), but it will not sound better when playing raw samples. Plus if you show me your code for CPC old, I'll be able to help you. I don't know how to code for CPC Plus.

Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 13:07, 25 February 19
Quote from: Shining on 17:25, 22 February 19

Currently I'm a little bit playing with the plus and I want to output a sample by using the dma.

I've done the following:

- exported a sample (8kHz) unsing audacity->Export Audio->Other uncompressed files->RAW(header-less)->Signed (8-bit PCM)
- wrote a little programm which converts the 8-bit values to 4-bit, using the table which was generated from this example: http://cpctech.cpc-live.com/source/sampplay.html (http://cpctech.cpc-live.com/source/sampplay.html)

- Put the sample into a cartridge-page

Now on Plus:

- Begin at adress 0x4000 (RAM is mapped)
- write 3f, 06 ( mixer register, disable tone and noise)
- Write sample-byte, write 0x08 ( volume register channel A) and so on for all sample bytes
- after the last sample-bytes write 0x20 0x40 (STOP Stop processing the sound list)

- Now I write 0x4000 to 0x6c00,0x6c01 (Channel 0 address), a 0x01 to the Channel 0 prescaler (8 kHz) and 0x01 to 0x6C0F (Channel 0) enable (IRQs are off, DI)

- Now I hear something but it sounds only like noise and it seems to correctly stop at my 0x4020-command and disables the DMA then.



At the moment, I've no clou what I've done wrong. My first guess is, that I've done something wrong with the sample.
Any ideas ?



Sorry but mixer register is 7 not 6.
To play your sample, you ´ll Just have to read these posts -> http://amstradplus.forumforever.com/t499-La-Programmation-sur-Cpc.htm (http://amstradplus.forumforever.com/t499-La-Programmation-sur-Cpc.htm) about digidrums & samples.
You probably will find what you are looking for.
Title: Re: Sample-Playback on Plus-DMA question
Post by: Shining on 14:42, 25 February 19

Thanks @all for your useful tips  :) ! Especially how to convert my samples to sound better on CPC.


Quote from: Ast on 13:07, 25 February 19

Sorry but mixer register is 7 not 6.



That was the problem with my driver! I used the noise register, so I only got noise. So as always, the problem was sitting in front of the monitor. 8)


Now the dma plays my sample...
Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 18:40, 25 February 19
And the winner is....


Congratulations @Shining (http://www.cpcwiki.eu/forum/index.php?action=profile;u=922)
Title: Re: Sample-Playback on Plus-DMA question
Post by: andycadley on 18:53, 25 February 19
Neat. This is one of those things I keep meaning to play around with a bit, so it's good to see the tips in this thread.
Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 04:15, 26 February 19
Thanks for this! I've been working on digital sound playback testcode on all the systems in my programming tutorials, but I've not looked at the CPC+ DMA yet...

I've also written my own converter program, but I'm just using a linear conversion at the moment, so I need to try out the 'weighted' lookup in the code here, as I'm sure it will improve the resulting sound.

Thanks,
Keith
Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 12:37, 27 February 19
OK, I've got a single sound sample created and playing back with the CPC+ DMA,
Can I just check that I have a few things understood correctly, as they seem a little odd..

1. Each sample is 4 bit, but due to the dma's required format requires 1 word (16 bit)

2. There is no way to slow playback down below 15khz, without adding 'pause commands' between samples or NOPS, which would add another 16 bits

so effectively, for a 'single sample'*,  you will be using a minimum of 4x what playing the sample would take with a 'software' solution where 2 samples were packed into a byte?... it's taken my 'test sample from around 7k to around 28k - half the cpc ram!

I only ask, because that seems a huge amount so I'm wondering if I'm mistaken - especially when the sample has to be in the base 64k of ram.

* I'm aware I could probably stream new bytes into a DMA buffer during interrupts, or use lots of samples and repeats to make up larger samples - I'm talking about a 'simple' case.
Title: Re: Sample-Playback on Plus-DMA question
Post by: roudoudou on 13:08, 27 February 19
Quote from: keith56 on 12:37, 27 February 19
so effectively, for a 'single sample'*,  you will be using a minimum of 4x what playing the sample would take
There is many repetitions in almost any samples, so when there is moar than 2 identical values you can set the value, then pause n-1



Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 13:32, 27 February 19
Quote from: roudoudou on 13:08, 27 February 19
There is many repetitions in almost any samples, so when there is moar than 2 identical values you can set the value, then pause n-1
Thanks! I've added this to my program, and the sample is down to 14k... half the size!


Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 14:51, 27 February 19
Quote from: keith56 on 10:45, 01 December 74

1. Each sample is 4 bit, but due to the dma's required format requires 1 word (16 bit)

2. There is no way to slow playback down below 15khz, without adding 'pause commands' between samples or NOPS, which would add another 16 bits



1. Yes, each sample is 4 bits max !
2. You could also use the PPR register (try it!)
Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 15:25, 27 February 19
Quote from: Ast on 14:51, 27 February 19

1. Yes, each sample is 4 bits max !
2. You could also use the PPR register (try it!)

But am I right in saying the PPR only slows down PAUSE commands? I did try values from 0-200, and if there are no pause commands in the stream, there was no noticeable speed difference (unless I'm using it wrong)
So to use the PPR to slow down playback, I may have to add PAUSE commands where they were not otherwise needed?
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 15:29, 27 February 19
Quote from: keith56 on 12:37, 27 February 19
OK, I've got a single sound sample created and playing back with the CPC+ DMA,
Can I just check that I have a few things understood correctly, as they seem a little odd..

1. Each sample is 4 bit, but due to the dma's required format requires 1 word (16 bit)

2. There is no way to slow playback down below 15khz, without adding 'pause commands' between samples or NOPS, which would add another 16 bits

so effectively, for a 'single sample'*,  you will be using a minimum of 4x what playing the sample would take with a 'software' solution where 2 samples were packed into a byte?... it's taken my 'test sample from around 7k to around 28k - half the cpc ram!

I only ask, because that seems a huge amount so I'm wondering if I'm mistaken - especially when the sample has to be in the base 64k of ram.

* I'm aware I could probably stream new bytes into a DMA buffer during interrupts, or use lots of samples and repeats to make up larger samples - I'm talking about a 'simple' case.
Go for double buffered interrupt driven replay routine :) - it will take sample size+2*buffer for each channel.
When I get back home I can post an example if you are interested.
Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 15:32, 27 February 19
Quote from: Docent on 15:29, 27 February 19
Go for double buffered interrupt driven replay routine :) - it will take sample size+2*buffer for each channel.
When I get back home I can post an example if you are interested.

No need, thanks, I can imagine what it looks like, really I'm just looking for a 'simplest' example of using the DMA for my tutorial series - and I'm trying to make sure I understand the limitations of the way the CPC does it correctly... I don't want anything using interrupts in this case, for one thing I thought the idea of a DMA was to save you having to do that kind of thing (do CPU work during interrupts).
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 15:47, 27 February 19
Quote from: keith56 on 15:32, 27 February 19
No need, thanks, I can imagine what it looks like, really I'm just looking for a 'simplest' example of using the DMA for my tutorial series - and I'm trying to make sure I understand the limitations of the way the CPC does it correctly... I don't want anything using interrupts in this case, for one thing I thought the idea of a DMA was to save you having to do that kind of thing (do CPU work during interrupts).
The simplest dma example, as you find out, will require 16 bit per sample. This is how the sound dma on cpc plus works - it needs to know which audio register to feed with data.
The solution I suggested still uses dma, but replays a sample divided into buffer-sized chunks. When the dma finishes playing current chunk it triggers interrupt to feed the buffer with next chunk of sample data.
But for a tutorial this might be an overkill :)
 
Title: Re: Sample-Playback on Plus-DMA question
Post by: andycadley on 22:39, 27 February 19
Quote from: keith56 on 15:25, 27 February 19
But am I right in saying the PPR only slows down PAUSE commands? I did try values from 0-200, and if there are no pause commands in the stream, there was no noticeable speed difference (unless I'm using it wrong)
So to use the PPR to slow down playback, I may have to add PAUSE commands where they were not otherwise needed?

That's my understanding too. I suspect any workable solution needs to generate the DMA programs from more tightly packed data, which is a bit annoying. If the pre-scaler could be applied to other commands it would have been nicer, but you have to work with what you have. The Plus hardware can still push data to the AY faster than the CPU ever can, so as long as you can work around it you can get better results. It's another one of those cases where the Plus hardware is really designed around the assumption you are running from cartridge and thus the 64K RAM is staggeringly huge amounts of workspace compared to rival consoles.
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 02:02, 28 February 19
Quote from: keith56 on 15:25, 27 February 19
But am I right in saying the PPR only slows down PAUSE commands? I did try values from 0-200, and if there are no pause commands in the stream, there was no noticeable speed difference (unless I'm using it wrong)
So to use the PPR to slow down playback, I may have to add PAUSE commands where they were not otherwise needed?
Yes, PPR slows down execution of pause command only, so in your dma list you need something like this:

macro LOADREG r,d
db d, r
endm
macro DMA_PAUSE n
dw #1000+n
endm
....
LOADREG 8, snd_data
DMA_PAUSE pause_cnt
...

The problem is that it will slow down the replay even if you use 0 prescaler value. This is due to the way dma works - each 16bit value is fetched per line, so adding a pause 0 cmd (actually any command will do, even nop) cuts down your replay speed by half.
Title: Re: Sample-Playback on Plus-DMA question
Post by: keith56 on 04:20, 28 February 19
Great! Thanks for everyone's feedback,I've got my sample code working, and I think I have this understood well enough to do my tutorial!

I'll be covering playing a WAV on everything from the Speccy to the Gameboy, including the CPC/CPC+ so it should be quite fun!
Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 12:49, 28 February 19
Quote from: keith56 on 15:25, 27 February 19
But am I right in saying the PPR only slows down PAUSE commands? I did try values from 0-200, and if there are no pause commands in the stream, there was no noticeable speed difference (unless I'm using it wrong)
So to use the PPR to slow down playback, I may have to add PAUSE commands where they were not otherwise needed?


Yes, you are right !
Title: Re: Sample-Playback on Plus-DMA question
Post by: Shining on 20:18, 28 February 19
By the way. I heavily use packers like exomizer in my productions but are such packers/depackers able to depack data like a stream ?
So that I can fill a buffer out of depacked data?


The sample, I want to play is targeting GX4000/464 64KB and is still too big...
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 21:27, 28 February 19
Quote from: Shining on 20:18, 28 February 19
By the way. I heavily use packers like exomizer in my productions but are such packers/depackers able to depack data like a stream ?
So that I can fill a buffer out of depacked data?


The sample, I want to play is targeting GX4000/464 64KB and is still too big...
I haven't heard about a packer for cpc with streaming support.
You can easily adapt any packer for such purpose - split source sample into chunks of replay buffer size and pack each chunk separately, add a byte at the beginning of packed chunk with the size of packed data and write all chunks sequentially to file. Depack single chunk when a buffer is available to fill and you'll get some sort of streaming.
Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 21:36, 28 February 19
Instead of replaying 15khz samples data, you could try to use 8khz ?
Try to use more and more loop, that's the key!

Title: Re: Sample-Playback on Plus-DMA question
Post by: dthrone on 10:32, 01 March 19
Just chiming in with what I've found practical.  My (far from optimised) player sends 4k samples to the 3 channels and stores 2 frames-worth of DMA list per channel in the RAM.  It buffers in new lists every frame and that process takes 15-20% of frame time in total for the 3 channels.  I can live with that processing time and the hit on the RAM is minimal. 


Big hit is on the storage but like Ast says, if you use loops, have good compression and unpack routine etc. and most importantly, are using a 512k cart, it's feasible to have all your sfx in samples.


Sound quality of the 4k samples really isn't too bad!
Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 12:48, 01 March 19
Quote from: dthrone on 10:32, 01 March 19
Big hit is on the storage but like Ast says, if you use loops, have good compression and unpack routine etc. and most importantly, are using a 512k cart, it's feasible to have all your sfx in samples.


Best example is Eerie Forest by Overflow/Logon -> http://www.pouet.net/prod.php?which=72271 (http://www.pouet.net/prod.php?which=72271)
As you can see, it's Possible to do really cool things !
Title: Re: Sample-Playback on Plus-DMA question
Post by: Shining on 12:29, 03 March 19
Im already using looping and when I use 8kHz, I need pause-commands but I'll consider that. At the moment I'm using the complete data in the cart but when I'll do something like dthrone, I think, I'll get the size down to what I want.


So by using a buffer instead of the complete list, I do not need the 8kHz pause command in the list (in cart) and I can save two 4-bit values in one byte..
Title: Re: Sample-Playback on Plus-DMA question
Post by: dthrone on 00:39, 04 March 19
Quote from: Shining on 12:29, 03 March 19

So by using a buffer instead of the complete list, I do not need the 8kHz pause command in the list (in cart) and I can save two 4-bit values in one byte..


Exactly, you only need to update the details of each (buffer) list each frame in the RAM, not the structure that is static.


I've not analysed the Eerie Forest code, they've probably got a really smart way of doing it  8)
Title: Re: Sample-Playback on Plus-DMA question
Post by: Docent on 12:53, 04 March 19
Quote from: dthrone on 00:39, 04 March 19

Exactly, you only need to update the details of each (buffer) list each frame in the RAM, not the structure that is static.
Or trigger an interrupt at the end of dma list to refill the list with new audio data and restart playing it.
You can change the size of the list and the interrupt will be triggered at the right time.
btw: this is what I suggested earlier as double buffered interrupt driven replay routine.
 
Title: Re: Sample-Playback on Plus-DMA question
Post by: Ast on 19:00, 04 March 19
Quote from: Docent on 12:53, 04 March 19
Or trigger an interrupt at the end of dma list to refill the list with new audio data and restart playing it.



Of course, you could do it !  ;D
Powered by SMFPacks Menu Editor Mod