Open rafagan opened 4 years ago
Thanks!
Can you give more detail about what type of pitch shift you are trying to implement?
I don't need time stretch, just some kind of tunning. Per example, at 0.5 rate, the sound would play more bass, and at 2.0 rate, the sound will reproduce like a chipmunk, more treble.
Which kind of info you need to know more to understand better?
Ráfagan Sebástian de Abreu
De: Joel Strait notifications@github.com Enviado: domingo, 12 de julho de 2020 07:10 Para: jstrait/jssynth jssynth@noreply.github.com Cc: Ráfagan Abreu rafagansa@outlook.com; Author author@noreply.github.com Assunto: Re: [jstrait/jssynth] Implementation of pitch shift (#8)
Thanks!
Can you give more detail about what type of pitch shift you are trying to implement?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/jstrait/jssynth/issues/8#issuecomment-657184539, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AARQNOKWPJFNHCG75GFJM6LR3FOVXANCNFSM4OW7HOXQ.
OK, that makes sense.
Changing the sample rate of an audio file will change the pitch and playback speed. For example, if a file has a sample rate of 44,100, then changing the sample rate to 22,050 will halve the pitch and playback speed.
If you are working with actual sample data, here is how to do it. Let's say you have this list of samples: [4, 7, -1, -2, 1, 5, 6, 2, 0, -3]
Then to change the pitch and playback speed, you need to change how fast you move through those samples.
For example, at 1x speed, you would move through the samples one at a time: 4, then 7, then -1, then -2, etc.
At 2x speed, you would move through the samples two at a time: 4, then two after that is -1, then two after that is 1, etc. (The final result being [4, -1, 1, 6, 0]
).
However, if the playback rate is not an integer multiple, then you have to interpolate samples. For example, what if the playback rate 1.5x? First you have 4, but then the next sample 1.5 samples away, which is halfway between 7 and -1. So you have to create a "virtual sample" instead. For example, if using linear interpolation, the virtual sample would be 3, because that is halfway between 7 and -1. (The final result of 1.5x speed being [4, 3, -2, 3, 6, 1, -3]
);
Here is some pseudocode to show the idea:
playbackRate = 1.5 // Shift pitch up 1.5 times, and play back 1.5 times faster
inputSamples = getInputSamples()
outputSamples = []
sampleIndex = 0.0
while (sampleIndex <= (inputSamples - 1)) {
// Use linear interpolation to create a "virtual sample" between two adjacent samples
leftSample = inputSamples[floor(sampleIndex)]
rightSample = inputSamples[ceiling(sampleIndex)]
percentage = sampleIndex - floor(sampleIndex)
interpolatedSample = ((1.0 - percentage) * leftSample) + (percentage * rightSample)
outputSamples.push(interpolatedSample)
sampleIndex += playbackRate
}
I don't know if linear interpolation is the ideal way to interpolate, or if there are better interpolation functions for audio. But this should give a result that works.
Like you said, this will change both the pitch and the playback speed. I haven't implemented pitch shift that doesn't change the playback speed, so I can't offer much help with that. 🙂
Hope this helps!
Very nice solution. I've tried something similar before, but it was very buggy: I was incrementing the sampleIndex using the pitch shift and I was always round down the sampleIndex to get the current frame, so for instance if the pitch shift is working in 0.1 play rate speed, the frame x would play 10 times before it reaches the x + 1 frame.
I'm researching about the linear interpolation and I've found this post:
https://stackoverflow.com/questions/21843564/linear-interpolation-audio-pitch-shift
Someone provided info about a pseudocode using sinc function. Do you know anything about that? http://www.nicholson.com/rhn/dsp.html#3
This algorithm that you provided is what you use for resampling techniques?
Hello Joel Strait, your work is amazing.
I'm currently working in an audio engine for low latency in Android and I'm trying to implement pitch shift. Do you have any clue to achieve that?