SynthMaker

PSOLA based real time pitch manager

Archive · 2011 23 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

martinvicanek ·

Hi,

here is a schematic that performs real-time monophonic pitch manipulations such as simple fixed interval pitch shift, harmonizer, octaver, subtle detune (5 to 10 cents makes a nice chorus-like effect), pitch quantize to scale, pitch correction, MIDI controlled pitch, diatonic (= scale respecting) pitch shift, chipmonk or Klingon voice. At the core is a PSOLA based pitch shifter, which is controlled by the output from a pitch extractor from another thread Pitch Extraction. I have tested it with voice and guitar input, but other monophonic sources should work as well.

While chipmonk voice may be funny for a while, I think for serious musical applications one would prefer to have separate control over the fundamental and the formant shifts, respectively. I am working on that (basically taking a vocoder approach), but it is not yet ready for release.

Oh, well, the GUI is - uhm - very basic, I hope that will not put you off. I really admire the level of sophistication in many GUI artworks found here around. That is really way beyond me.

Anyway, hope you like this one. Your comments and suggestions for improvement are very welcome!

Martin

philter5 ·

thx for sharing. i´ll be back with some comments 😉

RunBeerRun2 ·

Looks cool, I've run it on an mp3 so far, the adjust to scale part definitely works, I'll try it with a microphone soon.

Gui doesn't put me off, the only thing that bugs me is hardware knobs. Hardware is durable, not attractive.

Edit: sounds pretty good, I sang along with an mp3, didn't sound too cheap. I'll try it out later in my own songs.

stw ·

Thanks for sharing Martin, good work!

RunBeerRun2 ·

This one is pretty fun! I connected midi in to a midi out and use it with a vocoder.

martinvicanek ·

Here is an update of my project - now with independent pitch and formant control. That opens up a range of additional possibilities like formant preserving pitch shifting, voice "gender" manipulation etc. And all that in real time 😉

After messing around with the vocoder approach for a while I finally took another route. From hindsight is seems so embarrassingly straightforward, and it's all written there at http://www.dspdimension.com/admin/time-pitch-overview/. In a nutshell, you slice the input stream in pitch-synchronous chunks and drop them at a (possibly) different rate and playback speed to the output stream. The drop rate is just the output frequency, while the playback speed determines the formant shift.

Have fun!

P.s. One thing I have not figured out is how to make it polyphonic when using MIDI input for pitch control. When I replace the MIDI2mono primitive by MIDI2poly, all blue connections turn white and SM crashes 🙁 I think that's because the pitch extractor module uses mono4 which seems to clash with poly? Too bad, as the pitch extraction actually does not need multiple instances (only the pitch shifting module does).

RunBeerRun2 ·

Sounds real cool, I'll definitely be using it. Needs a denormal reducer, I tried it on my Pentium4 and the cpu went from 7 to 70%. I think I put one in on the last version.

Yeah I don't think the pack4 module allows poly, I use it often with synths, packing/unpacking FM modulators or just detuners and there's missed notes with any poly.

infuzion ·

Thanks for sharing & your upkeep!

martinvicanek wrote: One thing I have not figured out is how to make it polyphonic when using MIDI input for pitch control. When I replace the MIDI2mono primitive by MIDI2poly, all blue connections turn white and SM crashes 🙁 I think that's because the pitch extractor module uses mono4 which seems to clash with poly?

You can "Pack" Poly: Stereo Phaser Attached are some replacements for Mono Pack4 & UnPack4 to their Poly versions. Keep in mind: Mono connecting into Poly = only channel 0 will carry the Mono input. I've tested the individual parts, but not your entire OSM with my replacements. See if they work please.

I assume you'll have to do some more re-programming to make it truly Poly, since your calculations seems to be only for 1 channel? Maybe we are lucky & you don't have to reprogram...

stw ·

A different poly approach but i guess that's the wanted effect? Center note is C1 (60). The shift offet is created from this note independently from the input pitch. However the nature of poly sections is that a voice has to be initiated. So there won't be any output until a note is pressed. If it should run in blue (audio mode) either there has to be another mono section to do it or a fake voice has to be created.

martinvicanek ·

Thanks for your feedback, guys! Will get back with more detail, but from first glance stw's idea to use Mono2Poly seems to do the trick of blocking the back propagation of white connections to the pitch extractor. Looks good! I also appreciate RBR's and infuzion's comments but need more time to investigate.

MegaHurtz ·

sounds good!

martinvicanek ·

Okay, here is the poly version (thanks stw!). Hook a mike to audio in, set Pitch Control to "MIDI". Simultaneously press Z-C-B (on a US keyboard), and sing (or just say) something to produce a C major chord. Or if you like it more jazzy try this progression (Cmaj7 Cm7 Fm6 C6): B-M-Q-E B-J-Q-3 V-H-Q-W Z-C-B-N For more serious work you might want to use a MIDI keyboard...

Have fun!

RunBeerRun2, how do you get denormals, please? I'd like to fix that, however I have not been able to reproduce the bug here.

RunBeerRun2 ·

I don't remember if the denormals came after switching buttons or just running audio through, then stopping.

CPU evened out when I put the stock SM denormal thing as the 1st module.

trogluddite ·

Some excellent work there again, Martin. 🙂 I've been experimenting with granular time/pitch stuff for a while, but your .osm has shown me that I definitely misread a few things when I was studying the PSOLA theory - finally I have grasped how the pitch and formants can be made independent! Thankyou

. martinvicanek wrote: how do you get denormals, please?

Denormals are just numbers that are so small that they can't be represented using the usual float number bit patterns. Because of this, they require a lot more CPU power to process than regular float numbers.

They mostly happen because of feedback loops with a exponential decay. Any soundcard input will be well above the limit for de-normal numbers, so as long as there is audio passing through, you generally don't see the problem. As soon as the input goes silent, the numbers in feedback loops start decaying - but an exponential decay never truly reaches zero, it just gets smaller and smaller until it goes below the 'denormal' limit, and them chews up your CPU.

In this case, the most likely candidate is your filters - the denormal problem affects all infinite impulse response filters.

There are ways around this by killing the denormals as they happen inside the filter feedback loops - but as there are so many hard-coded filters in your design, runbeerrun's method of feeding very low level noise into the input is by far the simplest solution. The noise is at such a low level that you could never hear it (far lower even than dithering noise) - but it s just enough to keep the numbers inside the filter feedback paths above the denormal limit, even if the audio input is silent.

Mo ·

martinvicanek wrote: I'd like to fix that, however I have not been able to reproduce the bug here.

Denormals are easily detected by a boolean connected to the audio in, then switch it on/off and look at the CPU-meter. IMO the best way to avoid it is to add 1e-008 then subtract 1e-008 in the feedback loops. If you choose low noise to avoid DC, it should be filtered off with HP before the output.

martinvicanek ·

Thanks for your insight, guys. The reason why I am not getting denormals is probably due to my low grade onboard audio adapter. The noise it generates is insane, certainly way beyond 1e-008 or anything. However, I realize that you can feed the circuit with another source that actually might go to zero and hence produce denormals. As to the stock denormal remover, isn't it a bit costly to compute sin1() at sample rate just to generate noise at -180 dB? I mean it does not have to be white noise, does it? Any other tiny signal would do, e.g. a square wave at Nyquist frequency would be much lower on CPU.

stw ·

martinvicanek wrote: As to the stock denormal remover, isn't it a bit costly to compute sin1() at sample rate just to generate noise at -180 dB? I mean it does not have to be white noise, does it? Any other tiny signal would do, e.g. a square wave at Nyquist frequency would be much lower on CPU.

It certainly is! Right now i use another noise generator which is hopped at 1024. It uses almost no CPU and does the job pretty well. But your idea of a simple square is an interesting idea. I've no idea if that could cause any unwanted effects. I did a short try and it seems to work as well.

trogluddite ·

Depending on the decay time of the feedback loops, it's OK even to send mostly zero's. This little code sends a 1e-12 pulse every 1024 samples, and seems to kill the denormals effectively.

streamout pulse;

float amount=1e-12;

pslld xmm0,32; //Fast set to zero mov eax,ecx; and eax,1023; jnz end0; movaps xmm0,amount; end0: movaps pulse,xmm0;

Could possibly be improved by making the pulses toggle in polarity - but as it is only one sample every 1024, there is very little energy being put into the feedback loops, and (theoretically at least) a pulse is spread very thinly across the frequency spectrum.

stw ·

trogluddite wrote: Could possibly be improved by making the pulses toggle in polarity - but as it is only one sample every 1024, there is very little energy being put into the feedback loops, and (theoretically at least) a pulse is spread very thinly across the frequency spectrum.

I don't know if it's more or less efficient (maybe more bacause it does all ops in the hop) but this is the code i tried for the square. Seems to work as well.

streamout sq; float F1eM009=1e-009; float F0=0;

stage0; movaps xmm0,F1eM009; movaps sq,xmm0;

stage2; mov eax,ecx; and eax,1023; cmp eax,0; jnz end0;

movaps xmm0,F0; subps xmm0,sq; movaps sq,xmm0;

end0: stage2;

infuzion ·

Test for Denormals + more: A geek toy: Stream inspector

mccy ·

Just a question about the modules in your pitch manager: I am a Music-teacher & I showed some pupils today that they can sing like their idols 😉 by putting their voice through your algos. One boy asked me, if I could give him a program, with which he can do the same at home. By now he does not know what a vst is, so I had the idea to make an exe for such voice experiments for pupils. Would it be O.K. to do so? Even a vst? They might share it, but I guess noone would load it up anywhere.

What do you think about it?

martin

martinvicanek ·

Hey Martin, I'd be happy to see my stuff being used for educational purposes, so yes, by all means, please go ahead with your project. And say "hi" to your kids from uncle martinvicanek 🙂

mccy ·

Great! Thanks!

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.