A Simple BASS Question?

Started by davekerr,

davekerr

Hi,
I'm writing a little app that loads up songs in MP3 format, and allows you to split them into sections, using BASS. It's for musicians who want to be able to practice certain parts of songs over and over. It's working well, but I want to be able to slow down a section of a song (say, a fast guitar solo) without altering the pitch.
I thought I'd do this by calling 'GetData' on the channel that represents the MP3 and storing the data in an array, then I make an array twice as long, and but every element from the first array in twice. This would 'slow' down the song, without altering the pitch.

However, 'GetData' always throws an exception, I call it on an array of shorts. Can anyone explain what I'm doing wrong?

Also, after I've got this array, I was planning to make it into a sample, so the user could play it back, is this the right way to do this? I'm new to programming with sound, thanks in advance!!

Smayds (Guest)

Hi Dave,

Just thought I'd mention that if you just duplicate each sample in the array (i.e. each sample is played twice), the pitch will indeed drop, as the sound will be effectively played at half the sample rate.

What you need to do is either (easier) split the sound up into lots of little chunks, say ~100-200 samples long, and play each chunk twice; or (harder) track the waveform as it moves about the zero point, and duplicate each chunk (of variable length) after it crosses the zero point twice (once up, once down, for example).

How about some code snippets? Then maybe we could tell you what you are doing wrong! I have no problems with GetData.

-Ayden

davekerr

Hi there,

OK, here is the code I'm using to try and make a 'half speed' same pitch file.


stream = bass.LoadStream(false, info.FullName, 0, 0, 0);      
int size  = (int)stream.Length;
short[] data = new short[size];
           
// Now create a new buffer, twice the size.
short[] newdata = new short[size * 2];

for(int i=0; i<size; i++)
{
     newdata[i*2] = data;
     newdata[(i*2)+1] = data;
}

Sample sample = bass.CreateSample(newdata, stream.Attributes.Frequency, 5, SampleInfoFlags.Default);


Ok that's the gist of the code.
The code is for nBASS (it's in C#) so creating arrays is somewhat easier, but I'm not sure where I'm going wrong, how would I implement the first method you mentioned?

Thanks

Dave

Smayds (Guest)

Hi Dave,

Very simply:

int ChunkSize=100;

for(int i=0; i<(size/ChunkSize); i++)
{
    for(int j=0; j<100; j++)
    {
        newdata[i*ChunkSize*2+j] = data[i];
        newdata[i*ChunkSize*2+j+ChunkSize] = data[i];
    }
}

This will duplicate smallish bits of sound (set via chunksize). When played pack, you might notice some small clicks & pops, which is why the second method is better, as it only repeats a chunk when it crosses the zero line.

Are you still having problems with GetData? That was the code I was meaning that you post.

-Ayden

Smayds (Guest)

Whoops! Silly me, it's late... Yawn!

int ChunkSize=100;

for(int i=0; i<(size/ChunkSize); i++)
{
    for(int j=0; j<100; j++)
    {
        newdata[i*ChunkSize*2+j] = data[i*ChunkSize+j];
        newdata[i*ChunkSize*2+j+ChunkSize] = data[i*ChunkSize+j];
    }
}

-A

bigjim

Hi,
I think splitting the song into sections will be easy enough, but unless I'm mistaken you want to slow the song without altering the pitch (timestretching) but as far as I know- simply duplicating the sample will not work :(

To timestretch properly is hard from what I've read, you need to do something like a vocoder method or something like that, it seems to inovlve doing fft like analysis of the sample data.

Your best bet is to try and find an algorithm somewhere on the net or in a book, but from what I've found its far from easy.
www.dspdimension.com has some stuff about pitch scaling which is a similar subject.
Hope this helps but as far as code goes I think its a bit out of my depth.

Good luck ;D

Smayds

Hi all,

I just tried my own example for the first time ;-) and it seems to work fine. There are a few pops and crackles, but they're very quiet compared to the sound.

Give it a try!

-Ayden