www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Dynamic pitch shift

reply Tanel =?UTF-8?B?VGFnYXbDpGxp?= <tanel58 hotmail.com> writes:
Hello!

I've been making some progress on the native D audio front:
https://github.com/clinei/daud/tree/28ac042a16ae6785605a9a501b5f867c8f962055

It's a continuous waveform generator, currently outputting a saw 
wave that changes pitch every 1K frames.

I have a slight problem, however.
Due to the frequency changing in the middle of a wave, I have to 
patch the new waveform together with the last, which I've done 
with `countUntil` at daud/gen.d:211 (I don't need to call 
popFrontN because the range is a reference type).

However, when calling `RepeatingGenerator.frequency`, the value 
of `_repeat.front` is not the value of the last frame.
app.d:61 is a temporary hack.


How could I get the value currently passed through `cont` from 
`_repeat`?
Feb 24 2016
next sibling parent reply Tanel =?UTF-8?B?VGFnYXbDpGxp?= <tanel58 hotmail.com> writes:
Sorry for the confusing state of the codebase.

Only the saw wave generator is currently functional, the `saw` 
and `sine` functions are not used and should be left out of 
analysis.

Also, audio output is only to ALSA.
Feb 24 2016
parent reply Luis <luis.panadero gmail.com> writes:
On Wednesday, 24 February 2016 at 11:17:27 UTC, Tanel Tagaväli 
wrote:
 Sorry for the confusing state of the codebase.

 Only the saw wave generator is currently functional, the `saw` 
 and `sine` functions are not used and should be left out of 
 analysis.

 Also, audio output is only to ALSA.
Be careful with naive wave generators. You could get very funny artefacts from aliasing. You should try one of this approximations : - Correct naive wave generator : Use furrier composition to build the wave (ie, sum i=1->n An*sin(Wn*t + phase)), On this case, should drop of the sumatory the sin that generate armonics >= (Niquist freq)/2 This way, at least should be enough for sound testing, but isn't very efficient. See for example (C++) this Square wave generator against OpenAL (It needed some tweaks about just what you asked on the first post. The phase wasn't correct, but was enough for me on these moment) : https://github.com/Zardoz89/trillek-vcomputer-module/blob/78c9dd7bf0ead23cb9a8ccf29fd30c9d0ed7e2e5/tools/src/AlEngine.cpp#L210 - Wavetables - band-limited resampling algorithm aka BLIP or BLEP algorithms (See http://www.cs.cmu.edu/~eli/L/icmc01/hardsync.html and http://slack.net/~ant/libs/audio.html#Blip_Buffer )
Feb 25 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Thursday, 25 February 2016 at 15:15:20 UTC, Luis wrote:
 - Wavetables
 - band-limited resampling algorithm aka BLIP or BLEP algorithms 
 (See http://www.cs.cmu.edu/~eli/L/icmc01/hardsync.html and 
 http://slack.net/~ant/libs/audio.html#Blip_Buffer )
I suggest just porting STK from C++ to D. It is well documented, suitable for a D-range implementation, is written for clarity over speed and uses a BSD license: https://ccrma.stanford.edu/software/stk/ https://github.com/thestk/stk/blob/master/include/Blit.h It also contains a wide range of physical models (waveguides etc).
Feb 26 2016
prev sibling next sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 24 February 2016 at 10:33:56 UTC, Tanel Tagaväli 
wrote:
 Hello!

 I've been making some progress on the native D audio front:
 https://github.com/clinei/daud/tree/28ac042a16ae6785605a9a501b5f867c8f962055

 It's a continuous waveform generator, currently outputting a 
 saw wave that changes pitch every 1K frames.

 I have a slight problem, however.
 Due to the frequency changing in the middle of a wave, I have 
 to patch the new waveform together with the last, which I've 
 done with `countUntil` at daud/gen.d:211 (I don't need to call 
 popFrontN because the range is a reference type).

 However, when calling `RepeatingGenerator.frequency`, the value 
 of `_repeat.front` is not the value of the last frame.
 app.d:61 is a temporary hack.


 How could I get the value currently passed through `cont` from 
 `_repeat`?
So the buffer holds one period of the waveform? I'm assuming that you are nowhere near the Niquist limit. What is your harmonic distortion rate like? If it's just for audio how much additional distortion would you gain from just resetting the wave from the beginning? Also your static if (false) for debugging ... debug(statement) is a thing for a reason :) Nic
Feb 24 2016
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 10:33:56 UTC, Tanel Tagaväli 
wrote:
 Hello!

 I've been making some progress on the native D audio front:
 https://github.com/clinei/daud/tree/28ac042a16ae6785605a9a501b5f867c8f962055

 It's a continuous waveform generator, currently outputting a 
 saw wave that changes pitch every 1K frames.
Generating a saw waveform for an LFO is the same as generating the phase, which is easy to do with using D's modular integers. Just add the delta and let it wrap. If you are generating it for a VCO then you need a bandlimited oscilator: https://ccrma.stanford.edu/~juhan/vas.html (Abrupt changes in pitch will cause a discontinuity in the second derived which is audible, so you might want to interpolate.)
Feb 24 2016
parent reply Guillaume Piolat <name.lastname gmail.com> writes:
On Wednesday, 24 February 2016 at 14:02:49 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 24 February 2016 at 10:33:56 UTC, Tanel Tagaväli 
 wrote:
 Hello!

 I've been making some progress on the native D audio front:
 https://github.com/clinei/daud/tree/28ac042a16ae6785605a9a501b5f867c8f962055

 It's a continuous waveform generator, currently outputting a 
 saw wave that changes pitch every 1K frames.
Generating a saw waveform for an LFO is the same as generating the phase, which is easy to do with using D's modular integers. Just add the delta and let it wrap. If you are generating it for a VCO then you need a bandlimited oscilator: https://ccrma.stanford.edu/~juhan/vas.html (Abrupt changes in pitch will cause a discontinuity in the second derived which is audible, so you might want to interpolate.)
dplug:dsp has mipmapped oscillators https://github.com/p0nce/dplug/blob/master/dsp/dplug/dsp/wavetable.d Though it isn't fantastic aliasing-wise on the last octave, I should try something than power-of-2s next time I need it.
Feb 24 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 17:52:39 UTC, Guillaume Piolat 
wrote:
 Though it isn't fantastic aliasing-wise on the last octave, I 
 should try something than power-of-2s next time I need it.
Why would it help to not use 2^n sized tables? I guess you could compute everything at 88khz and decimate...
Feb 24 2016
parent reply Guillaume Piolat <contact gam3sfrommars.fr> writes:
On Thursday, 25 February 2016 at 07:02:24 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 24 February 2016 at 17:52:39 UTC, Guillaume 
 Piolat wrote:
 Though it isn't fantastic aliasing-wise on the last octave, I 
 should try something than power-of-2s next time I need it.
Why would it help to not use 2^n sized tables? I guess you could compute everything at 88khz and decimate...
We are not talking of the same thing. I was thinking about the table frequency cutoff which is 2x lower every level of mipmap
Feb 26 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Friday, 26 February 2016 at 13:21:12 UTC, Guillaume Piolat 
wrote:
 We are not talking of the same thing. I was thinking about the 
 table frequency cutoff which is 2x lower every level of mipmap
Ok. I think is most common to use high levels of oversampling for tables so one can get better SNR using cheap interpolation. But I've lately thought a bit about encoding the complexity of a segment of the function in the table so that the renderer can choose an interpolation technique that matches the location in the table (e.g. straight line, use lerp; high frequency wobble, use sinc). To make it work for realtime one would have to track the cost and revert to lower quality when the budget has been spent.
Feb 26 2016