For my fun musical hobby projects to continue my adventure into the world of audio programming I want to simulate a vinyl record scratch effect with the mouse using some sound data I have loaded from a WAV file.
I have it so I take the mouse start and end position and times and with a lerp stretch the samples into an audio output buffer. At the moment I am just point sampling.
It kind of sounds like a scratch sound but isn't quite right. I really just want something efficient that sounds good (I don't really want a whole physical simulation of a turntable) but I am not sure which areas I should be concentrating on to improve this?
Any help appreciated!
You also have to take into account the sound of the needle scraping the record.
If you move the zipper on a jacket or backpack quickly it can sound a lot like a scratch (depending on the zipper - smaller ones are better). Maybe you can record a few zippers and process them into something you can use.
That's interesting how would I do that? (Needle scraping sound)
Also I have been reading a little on FIR filters and it seems depending if the scratch causes a stretch I should fill the new gap samples with a zero and then run a FIR filter, or if it shrinks it run an FIR filter and then discard any samples to be skipped over.
But what kind of FIR filter would be best?
Maybe you just shouldn't do pointsampling. Perhaps using some kind of mipmapping scheme where you recursively downsample the soundbuffer in half, and then based on the speed of the mouse selecting one of the "mipmaps" to sample from would make it sound better.
I coded this, all i did for this was to change the playback speed to catch up to where the mouse cursor was at (even to play backwards of course), it sounds like a scratch, but its a "digital scratch" it doesnt take into account of the pin scratching sound.
As far as that goes, its still useful and saleable already, I dont think its expected you to go to the lengths to get exactly the same sound as a vynil turntable.
What youve got already probably is good enough, thats all im saying.
It does sound fairly noisy at the moment though so which is why I wonder about filtering. I have been reading that I should maybe use a sinc FIR filter sin(x)/x but I am not sure how I should design the number of coefficients etc.
When you said you altered the playback speed to catch up do you mean you changed the speed so it was such that it match the velocity between the start and end scratch points given the time delta? Also would this effectively give you filtering for free by the sound card I wonder? (I use my own wrapper around XAudio2 and OpenAL presently). Also if you did that did you have time period after the scratch ended when the speed would gradually adjust back to the normal speed I assume?
My current code is something like:
void Scratch( AudioOutStream& audioOutStream,
int sampleRate = 44100;
int outputCount = ((int)sampleRate)*(scratchEndTime - scratchStartTime)/1000;
float recordRPS = 78.0f/60.0f; // The record rotates 78 times every 60 seconds => 1 rotation = 60/78 seconds
float scratchRotation = 45.0f/360.0f; // Scratch maximum angle
float scratchFactor = float(sampleRate)*scratchRotation/recordRPS; // 44 100 * (45/360) / (78/60) \~= 4240.38
float s0 = scratchFactor*scratchStartPosition;
float s1 = scratchFactor*scratchEndPosition;
// 44 100 / 4240.38 \~ 10.4 seconds
for(int outputIndex = 0; outputIndex \< outputCount; ++outputIndex)
float sampleIndex = float(heldNeedlePosition) + s0 + (s1 - s0)*float(outputIndex)/float(outputCount - 1);
// TODO: Wrap around properly!
if(sampleIndex >= sampleCount)
sampleIndex = 0.0f;
// TODO: Filtering?
In mine, you let go of the mouse button and it starts playing again, that would let you do the scratch type music.
What do you mean by noise? It should just sound like its changing tempo and pitch at the same time in the way you scrub the mouse.
I found that the distance you travel due to mouse speed is important, long scratches sound completely different to short scratches.
You don't take the RIAA equalization into account.
In a nutshell on a vinyl recording the bass frequencies are damped by up to 20db. The reason for this is among other things that strong bass-signals would cause the needle to jump out of the grove.
During playback the exact reverse filering is done to the signal (e.g. the bass is boosted by 20db).
In a normal playback situation the two filters cancel out and you hear the original recording (well - kinda.. the curves are always a bit off).
If you however play back the record at a wrong speed the filters don't match up anymore and you get a filtering response that's all over the place. This is part of the fat sound that you'll hear when you slow down the turn-table. In the extreme case you'll get up to 40db boost on the lowest frequencies that way.
To get a better scratch effect you have to apply the high pass filter to the raw .wav signal, and after playback (at whatever speed you want) you apply the inverse filter.
Make sure that you have a way to deal with *very* high signal levels. Inside the turn table the preamplifier will go into soft saturation.
You can simulate this if you just route the signal through a saturation function like tanh.
This will simulate a overdriven transistor pair almost perfectly. Adjust the amount of saturation to taste and you'll get a much better scratch effect.
Codes for RIAA emphases should be out there. Otherwise it's okay to just build one by concatening three simple lowpass/highpass filters in series.