News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Shining

Sample-Playback on Plus-DMA question

Started by Shining, 17:25, 22 February 19

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Shining


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

- 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
};
TGS is back

Download my productions at:
cpc.scifinet.org

TotO

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.

"You make one mistake in your life and the internet will never let you live it down" (Keith Goodyer)

roudoudou

Nah
Best result with dynamic compression, disregarding the AY range AND frequency replay
http://memoryfull.net/articles.php?id=4
My pronouns are RASM and ACE

Docent

#3
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.

Shining

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 ?



TGS is back

Download my productions at:
cpc.scifinet.org

Docent

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 :)

Docent

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.


mr_lou

Are there any 3-channel Amiga MOD => Amstrad Plus DMA conversion tools and players around?

Shining

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.
TGS is back

Download my productions at:
cpc.scifinet.org

Targhan

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.

Targhan/Arkos

Arkos Tracker 2.0.1 now released! - Follow the news on Twitter!
Disark - A cross-platform Z80 disassembler/source converter
FDC Tool 1.1 - Read Amsdos files without the system

Imperial Mahjong
Orion Prime

Ast

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

- 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 about digidrums & samples.
You probably will find what you are looking for.
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

Shining


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...
TGS is back

Download my productions at:
cpc.scifinet.org

Ast

_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

andycadley

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.

keith56

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
Chibi Akumas: Comedy-Horror 8-bit Bullet Hell shooter!
Learn ARM, 8086, Z80, 6502 or 68000 with my tutorials: www.assemblytutorial.com
My Assembly programming book is available now on amazon!

keith56

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.
Chibi Akumas: Comedy-Horror 8-bit Bullet Hell shooter!
Learn ARM, 8086, Z80, 6502 or 68000 with my tutorials: www.assemblytutorial.com
My Assembly programming book is available now on amazon!

roudoudou

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



My pronouns are RASM and ACE

keith56

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!


Chibi Akumas: Comedy-Horror 8-bit Bullet Hell shooter!
Learn ARM, 8086, Z80, 6502 or 68000 with my tutorials: www.assemblytutorial.com
My Assembly programming book is available now on amazon!

Ast

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!)
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

keith56

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?
Chibi Akumas: Comedy-Horror 8-bit Bullet Hell shooter!
Learn ARM, 8086, Z80, 6502 or 68000 with my tutorials: www.assemblytutorial.com
My Assembly programming book is available now on amazon!

Docent

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.

keith56

#21
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).
Chibi Akumas: Comedy-Horror 8-bit Bullet Hell shooter!
Learn ARM, 8086, Z80, 6502 or 68000 with my tutorials: www.assemblytutorial.com
My Assembly programming book is available now on amazon!

Docent

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 :)
 

andycadley

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.

Docent

#24
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.

Powered by SMFPacks Menu Editor Mod