An idea for an entirely new effect -- warning, long post

Petr Pařízek via audacity-devel <[email protected]> Sun, 16 May 2021 07:34:06 +0200
Newsgroups gmane.comp.audio.audacity.devel
Message-ID <[email protected]>
Hello to all of you,

to introduce myself a bit, I'm a piano player and a music composer and a 
music theorist who is very interested in things regarding digital audio 
effects. Many years ago, I wrote a lot of small programs for the old 
QBasic for DOS and currently I'm planning to start learning Nyquist in 
some near future.
FYI, I'm blind and that's why, when manipulating with the contents of a 
sound file, I often combine listening to the sound and converting the 
sample values to text, if I want to know more about some tiny details 
(where most people would probably zoom in the waveform).

I'm thinking of a possible new effect which might one day be implemented 
in Audacity. Currently, I'm absolutely unsure whether this kind of 
effect could be coded in Nyquist at all or whether the only way is to 
write such complex stuff in C or whether there's yet another way of 
doing it which I don't happen to know about. But I'd be super-happy if I 
were told that this thing could indeed be coded in Nyquist.
Therefore, I'll do my best to describe the effect, as some say, "in 
prose", and hope my description is understandable for you all. In case 
it isn't, I'm definitely open to clarification. I'll be very happy to 
know your opinions about what might be the best way to code this.
I'd like to stress that I'm not intending this effect for real-time 
performance at all, even though the description of the effect itself 
might make you think I am. I'm not even suggesting something like a 
"Preview" facility because I don't want the processing speed to be of 
any importance here. In every case, I'm willing to sacrifice speed over 
precision, even if the algorithm eventually turned out to be super-slow.
Although I'd love to have such a thing working one day, I'm even ready 
for the possibility that this effect might never be implemented, if I 
realize it would be too difficult for me to code (honestly, I've never 
coded in anything other than QBasic or briefly in Turbo Pascal, which 
would probably require me to learn C all from scratch if C turned out to 
be inevitable).

- The core part of the algorithm is a frequency shifter [1]. Unlike a 
pitch shifter, whose aim is to alter all the frequencies by a constant 
ratio, a frequency shifter alters all the frequencies by a constant 
difference.
- The corresponding dialog box would offer the following parameters:
1) the amount by which the frequencies should be shifted, given in Hz, 
which could be either positive or negative;
2) two volume settings, namely for "dry" and "wet";
3) the amount by which the wet signal is fed back into the input, given 
as a value that is less than 100% and more than -100%.
4) the amount by which the feedback is to be delayed, probably given in 
ms, which should always be given as a positive number; this parameter 
has no effect if feedback is set to 0.

[1] The actual realization would go like this:
- A) We store two intermediate copies of our original signal, label them 
"IP" and "Q", and modify them as described in [2],
- B) Each of the modified intermediate signals is separately 
amplitude-modulated:
IP is multiplied by a cosine wave of the given frequency,
Q is multiplied by a sine wave of the same frequency,
- C) we sum the two products to get the frequency-shifted signal,
- D) this signal, multiplied by the "Wet" coefficient, is sent to the 
output, together with the original signal multiplied by the "Dry" 
coefficient,
- E) the same frequency-shifted signal, this time multiplied by the 
"Feedback" coefficient and delayed by "Delay" ms, is sent back to the input.

[2] We make a filter that works like an inverted Hilbert transform, for 
which reason I'll call it the IHT. The length of the filter will 
probably be hard-coded and unknown to the user. The longer the filter, 
the closer the approximation gets to a proper IHT.
- For a positive integer l, the filter length should be either l*4 or 
l*4-1 samples. Practically, the two make no difference because every 
other coefficient is equal to zero.
- Even though the filter is l*4 samples long, our sample position 
indexes, instead of going from 0 to l*4-1, should go from -2*l to 
+2*l-1. Let's call them k. Similarly, for a filter of length 4*l-1, the 
sample position indexes k would go from -(2*n-1) to +2*n-1, i.e. from 
-2*n + 1 to 2*n - 1.
The actual values of the filter coefficients meet the following rule:
- For all even numbers k, the coefficient c(k) is equal to zero.
- For all odd numbers k, the coefficient c(k) is equal to -2/)k*π).
- Next, we convolve our original signal with this filter and store the 
result into an intermediate buffer, which may be called Q (as in 
"quadrature").
- Then, depending on whether our filter length is even or odd, we delay 
our original signal either by 2*n or by 2*n-1 samples and store this 
delayed copy into another intermediate buffer, which we may call IP 
(meaning "in phase").

You may be wondering why I insist on using an IHT instead of a proper HT 
or on multiplying IP by a cosine wave rather than a sine wave. The 
answers are:
- If I choose the amount of frequency shifting to be zero and do it the 
way I've described, the supposed frequency-shifted signal will only be 
delayed by "Delay" ms but in all other aspects it will be identical to 
the original sound -- i.e. there won't be any additional phase shifts or 
delays. In contrast, if IP were multiplied by a sine wave and Q were 
multiplied by a cosine wave, then the supposed frequency-shifted signal 
(with a zero frequency shift) would correspond to the original signal 
not just delayed but also Hilbert-transformed. This doesn't seem like an 
issue if the feedback is set to zero. However, once I set the feedback 
to a non-zero value, this thing starts to matter significantly.
- When I use an IHT, then I can get the desired frequency shift by 
adding the two amplitude-modulated signals. In contrast, if I used a 
proper HT, adding them would give me the opposite frequency shift and to 
get the desired one, I would have to subtract them.

Okay, that's it. Sorry for such a long post but I didn't want to miss 
any important details.

Thanks for your comments or suggestions.

Petr



-- 
Tento e-mail byl zkontrolován na viry programem AVG.
http://www.avg.cz



_______________________________________________
audacity-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-devel