News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Ast

Sample frequency

Started by Ast, 00:43, 27 December 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ast

hello,


My question is :


I've done a sample played using dma on Cpc Plus. How can i do to change the frequency of my sample.
For example, i play A note and i wanted to play A#. Can someone help me ?
_____________________

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 !

Ast

#1
Has anyone got an idea ??




















_____________________

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 !

Targhan

Sorry to ask, but how did you play Sids in one of your demo, whereas you can't imagine how to change a sample replay ?


Anyway... Playing one sample ("byte") every "tick" plays the sample at its normal frequency. Playing one sample out of two will double its replay frequency. Now you must find a way to play a sample and jump "less than a byte" further to play the intermediate notes. You can check my article on Push'n'Pop about Zooming, it's exactly the same thing.
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


Nice to see you Targhan.


I already know what you say here. What I want to know is :
How can I find the correct value ? Just doing that from scratch ? Earing each note ? Is it a faster way to precalc all that ?


Thanks.
_____________________

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 !

Prodatron

Have a look here:

Piano key frequencies - Wikipedia, the free encyclopedia

A has 440.000Hz, A# has 466.164Hz.
That means, you have to play the sample, which is based on A, 1,0594636times faster to get a A# (= 466.164 / 440.000).


GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

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 !

opqa

#6
Generally speaking, the frequency relation between 2 notes is given by 2^(n/12), where n stands for the number of semitones separating those two notes.

In your example n=1 as this is the distance between A and A#, it would be n=2 to pass from A to B for instance. Take in account that some notes are separated by 2 semitones while other only by 1, e.g: n=1 between E and F or between B and C.

Also, it would be helpful if you explained a little bit more what you're trying to achieve. If you want to make some kind of execution-time effect or transposition then you have to use this trick.

But if what you have is a sample and you want to transpose it just once and play it always the same in the CPC there are better ways to do it. The play-it-faster/slower trick to change pitch is effective, but it shortens of lengthens the duration of the sample as a side effect. Modern audio processing tools like Audacity can process a recording and change its pitch without affecting its duration. Though the best option, if you can, is just to redo the sample from scratch with the desired tone.

Prodatron

#7
I think it's impossible to play samples in realtime on the CPC with different pitches in a way, that their lengthes stay the same.
So I think the "simple" faster/slower methode is still the best one.
In Digitracker I used fixed-point values for moving the sample pointers (8bit+8bit IIRC). If it's played 1:1 the lower 8bit part is 0 and the higher 8bit part is 1.
Calculating such values can be done by using the formular by Opqa.

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

Targhan

If like me you don't like math, don't hesitate to do it by ear, it works fine :). After all, it's only 12 notes to find.
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

I'll try probably the 2 possibilities, and I'm certain to find some differences. 8)
_____________________

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 !

opqa

#10
I don't know how DMA playing works on the Plus, if calculating when to skip one sample needs to be fast and you don't need a lot of accuracy I've thought a way to do it that would be really fast. I involves only one 8-bit register and constant additions to it. I could explain it if you're interested.

Prodatron

Quote from: opqa on 16:33, 30 December 14
I don't know how DMA playing works on the Plus, if calculating when to skip one sample needs to be fast and you don't need a lot of accuracy I've thought a way to do it that would be really fast. I involves only one 8-bit register and constant additions to it. I could explain it if you're interested.

You probably know WEEE!s DMA music demo (unfortunately I can't find a video on YouTube...). AFAIK it's generating one 50Hz sample part for each channel in each frame with this byte skipping methode. The DMA of the Plus isn't able to play samples with different speeds in a way that you can play them like on the Amiga.

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

andycadley

Quote from: opqa on 16:33, 30 December 14
I don't know how DMA playing works on the Plus, if calculating when to skip one sample needs to be fast and you don't need a lot of accuracy I've thought a way to do it that would be really fast. I involves only one 8-bit register and constant additions to it. I could explain it if you're interested.
Definitely curious.

BTW, here's that DMA demo on YouTube


Cadjo Clan DMA Demo - YouTube

Ast

Prodatron, how can you forget
Prehistorik 2 with this fabulous Weee! Composition ?  :P
_____________________

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 !

Ast

Concerning Dma from Cpc plus, you must create an AyList which is composed of data like that :


AyList defw #0801,#0804...etc

Each AyList is finished by #4020.
Each AyList instruction is readed during the hbl !
So only one instruction per rasterline. You can
do more if you use vertical splitscreen
At the normal rate AyList is played at 15,625 kHz.
It's really good when you Know that a lot if samples on
Cpc are played in 8khz only !
_____________________

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 !

McKlain


Ast

And ....
Hate Beats from Ukonx. Power, the coder did a good job!
_____________________

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 !

opqa

#17
Quote from: andycadley on 19:16, 30 December 14Definitely curious.BTW, here's that DMA demo on YouTube
Cadjo Clan DMA Demo - YouTube

Ok then, here it goes.

Contrary to Targhan, I do like maths, so this is going to be a little bit mathemagical post. Also, all this is (more or less) untested theory and it may contain lots of errors.

Let's guess we are in the inital case Ast proposed, we want to increase pitch by a semitone, so as Prodatron pointed we need to play the sample ~1,0594631 times faster than the original. Playing it faster means we need to skip some samples from time to time but, how many? Taking the inverse of this quantity we have 1/1,0594631=0,943874. This means that we need to play about 94,4% of the samples and skip the rest. But we still don't know the "skipping interval". To calculate it we can write the above quantity like this:

0,943874 = 1 - 0,0561257 = 1 - 1 / 17,8172

The last expression can be interpreted this way, we need to shorten each sample 1/17,8172 of its original duration, as we can't do that, we can achieve the same effect just skipping one sample out of each 17,8172. Still, we can't do that, but we can round this number to its nearest integer and skip one sample out of each 18. This way we would be playing at a rate:

1 - 1 / 18 = 0,94444

Which is not bad approximation compared to its original value (0,943874). The code for doing so is somehow tricky, to skip one sample out of every group of 18 we need to count 17 and then increase the sample pointer by 1. Something like this.


; Sample skipping routine:
; INPUT
; HL - Pointer to the current sample
; B   - Partial counter, initially loaded to 17, it should be kept somewhere between calls

call play_sample
inc hl
dec b
ret nz
inc hl
ld b,17
ret

This is a quite accurate match in this particular case, but it can be improved doing a little bit more math, more on this later.

opqa

#18
Second part, we can improve the previous algorithm, but it will require some more maths and fine tuning by hand. Let's go back to this expression:

1 - 1 / 17,8172

Now, the trick, we are not going to round this number yet. Let's guess that, as before, we are going to count up to 16,8172 and then skip one sample. What we are going to do is to write this last number in an accurate fractional form. To do this, let's try to find a multiple of this number lower than 256 (that fits in a 8 bit register) which can be rounded to an integer more accurately. This is the hand-tuning part:

16,8172   x 1  =   16,8172
16,8172   x 2  =   33,6344
16,8172   x 3  =   50,4516
16,8172   x 4  =   67,2688
16,8172   x 5  =   84,086
16,8172   x 6  =   100,9032
16,8172   x 7  =   117,7204
16,8172   x 8  =   134,5376
16,8172   x 9  =   151,3548
16,8172   x 10 =   168,172
16,8172   x 11 =   184,9892 ~ 185
16,8172   x 12 =   201,8064
16,8172   x 13 =   218,6236
16,8172   x 14 =   235,4408
16,8172   x 15 =   252,258

The best match is highlighted, so we can write 16,8172 quite accurately as 185/11. By counting this number of samples and skipping one we would be playing at a rate:

1 - 1 / (185/11 + 1) = 0,943878

Which is almost a perfect match.

But 185/11 still isn't an integer number, so, how can we "count" up to it?. Easy, we can perform the "division" in real time using a single 8 bit register, keeping the remainder for the next division. This way, sometimes we will skip one sample out of 17 and sometimes we will skip one out of 18, but in the long term it would be exactly one skipped sample out of 17,8181...

The code for doing so would be like this.


; Sample skipping routine:
; INPUT
; HL - Pointer to the current sample
; A   - Partial counter, initially loaded to 185, it should be kept somewhere between calls

call play_sample
inc hl
sub 11
ret nc
inc hl
add 185
ret


Now, instead of decrementing the counter 1 by 1 we perform the division by subtracting 11. When the counter reaches 0 we know it's time to skip one sample. And, instead of resetting it to the same value, we just add 185 and start again, this way we are taking in account the remainder of each division for the next one.

Ast

#19
Just to know, what is this 'sub l1' ? :-\
Édit :
Oups Sorry after reading and reading again, i finally find 'sub 11' instead of 'sub l1'...
I think i'd need glasses  :D
_____________________

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 !

Prodatron

Btw in this way you can only generate the output for one octave.

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

Powered by SMFPacks Menu Editor Mod