0
0

Hello everyone,
I have implemented a simple scratch algorithm to emulate the classic vynil behaviour, it works but Im experiencing a problem:
the scratching doesnt follow the position in the right way. (the scratch is done with the mouse).

I mean: I click the mouse button and the sound stops, I go back and forth with the mouse and finally go back to the original mouse position but the position in the song is not the same as when I have clicked the mouse button.

Hope this is clear..

Here is the code:

[code:300etlkp]
private void PlayStream_Load(object sender, System.EventArgs e)
{
uint version = 0;

        /*
            Global Settings
        */
        result = FMOD.Factory.System_Create(ref system);
        ERRCHECK(result);

        result = system.getVersion(ref version);
        ERRCHECK(result);
        if (version < FMOD.VERSION.number)
        {
            MessageBox.Show("Error!  You are using an old version of FMOD " + version.ToString("X") + ".  This program requires " + FMOD.VERSION.number.ToString("X") + ".");
            Application.Exit();
        }

        result = system.setDSPBufferSize(512, 2);
        ERRCHECK(result);

        result = system.setSoftwareFormat(44100, FMOD.SOUND_FORMAT.PCM16, 2, 2, FMOD.DSP_RESAMPLER.SPLINE);
        ERRCHECK(result);


        result = system.init(1, FMOD.INITFLAG.NORMAL, (IntPtr)null);
        ERRCHECK(result);

        result = system.createSound("C:/House/Tae K - State of Emergency (Daft Punk + Jay-Z).mp3", (FMOD.MODE._2D | FMOD.MODE.SOFTWARE | FMOD.MODE.ACCURATETIME), ref sound);
    }

private void PlayStream_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
NewMouseY = e.Y;
mouse_seeker.Start();
}
}

    private void PlayStream_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left) 
        {
            NewMouseY = e.Y;
            mouse_seeker.Start();
        }
    }

    private void PlayStream_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left) {
            mouse_seeker.Stop();
            result = channel.setFrequency(44100);
            ERRCHECK(result);
        }

    }

    private void mouse_seeker_Tick(object sender, EventArgs e)
    {

        if (OldMouseY != -1000)
        {
            deltaMouseY = (OldMouseY - NewMouseY) * multiplier;
            channel.setFrequency(deltaMouseY);
        }

        OldMouseY = NewMouseY;
    }

[/code:300etlkp]

I have read from another way to implement the update is using a frame update function, but I dont absolutely know how to implement this…

Can someone help me?

thanks

  • You must to post comments
0
0

You’ll have to handle the setting of the frequencies in the update function of your main loop and handle the fact that it wont quite be exactly where you want when the mouseUp event occurs and add some logic to handle that case.

It’s best not to do these kinds of updates in the mouseMove event because it’s not likely to get called as frequently as your main update funciton.

-Pete

  • You must to post comments
0
0

any ideas? or there is something that is not clear?

  • You must to post comments
0
0

😳 pete im sorry but I cant understand well your reply…
can you expain it in a simpler way?

thank you

  • You must to post comments
0
0

Hi djmiky,

[quote:2g5mz5j8] I go back and forth with the mouse and finally go back to the original mouse position but the position in the song is not the same as when I have clicked the mouse button. [/quote:2g5mz5j8]
I would say the problem here is the interpolation between updates. Setting the instantaneous speed based on the difference of mouseY works in theory but in reality this doesn’t take into account the time taken for the channel to get updated, and the mixer thread being separate to the main thread.

[quote:2g5mz5j8]I have read from another way to implement the update is using a frame update function[/quote:2g5mz5j8]
I think you looking for the FMOD_INIT_SYNCMIXERWITHUPDATE system init flag.

You could also try calculating the desired absolute position of the channel using getPosition and the deltaMouseY, and then just setting the frequency of the channel to some value which will move it toward that position.

Hope this helps.

-Pete

  • You must to post comments
0
0

[quote="peter":2wzhjtp0]Hi djmiky,

[quote:2wzhjtp0] I go back and forth with the mouse and finally go back to the original mouse position but the position in the song is not the same as when I have clicked the mouse button. [/quote:2wzhjtp0]
I would say the problem here is the interpolation between updates. Setting the instantaneous speed based on the difference of mouseY works in theory but in reality this doesn’t take into account the time taken for the channel to get updated, and the mixer thread being separate to the main thread.

[quote:2wzhjtp0]I have read from another way to implement the update is using a frame update function[/quote:2wzhjtp0]
I think you looking for the FMOD_INIT_SYNCMIXERWITHUPDATE system init flag.

You could also try calculating the desired absolute position of the channel using getPosition and the deltaMouseY, and then just setting the frequency of the channel to some value which will move it toward that position.

Hope this helps.

-Pete[/quote:2wzhjtp0]
Hi peter,
thank you very much for your help, I really appreciate.

I have tried the FMOD_INIT_SYNCMIXERWITHUPDATE flag with system update called in the mouse_seeker_Tick routine,

[code:2wzhjtp0]
channel.setFrequency(freq);
if (system != null)
{
system.update();
}
[/code:2wzhjtp0]

but the sound comes out looped (half second loop).
Which is the problem?

Besides what do you mean when you suggest me to use getPosition and deltaMouseY?
do you mean to set the position in the mp3 proportional to the mouse movement? Im not sure to have understood…

  • You must to post comments
0
0

[quote:22uojpmd]but the sound comes out looped (half second loop).
Which is the problem? [/quote:22uojpmd]
The problem when mouse_seeker_Tick isn’t being called, you’re not calling update . Which means FMOD is not being updated so there is no new mix and the sound that is in the buffer keeps playing in a loop.

[quote:22uojpmd]what do you mean when you suggest me to use getPosition and deltaMouseY? [/quote:22uojpmd]

something like this [psueudocode]:

[b:22uojpmd]init[/b:22uojpmd]
channelDefaultFreq = channel->getFrequency

[b:22uojpmd]mouse down[/b:22uojpmd]
mouseStartY = currentMouseY
channelStartPos = channel->getPosition

[b:22uojpmd]mouse move[/b:22uojpmd]
mouseDeltaY = mouseStartY – mouseCurrentY
channelDesiredPos = channelStartPos + (mouseDeltaY * samplesPerPixel)

[b:22uojpmd]update[/b:22uojpmd]
channelCurrentPos = channel->getPosition
// calculate the delta of current and desired channel position
channelDeltaPos = channelCurrentPos – channelDesiredPos
// set a frequency value that will move the channel in the right direction
channelFreq = channelDefaultFreq * (channelDeltaPos * X)
channel->setFrequency(channelFreq)

‘X’ will be some factor which will depend on the rate at which update is being called. This will probably feel less responsive than your initial solution but it will make the channel position correspond more closely to the mouse position.

‘samplesPerPixel’ is the same as your ‘multiplier’ variable.

‘channelDefaultFreq’ is the same as the 44100 you had hard coded into your code, it’s better to use a variable to store the default frequency because not all sound files are 44100hz.

Hope this helps.

-Pete

  • You must to post comments
0
0

Hi pete,
thank you for your suggestion.
I have made some tests but I coudnt solve my problem.

Here is my code:

[code:5me8qktp]
MouseDown
mouseStartY = currentMouseY;
channel.getPosition(ref channelStartPos, FMOD.TIMEUNIT.PCMBYTES);

MouseMove
mouseStartY = currentMouseY;
channel.getPosition(ref channelStartPos, FMOD.TIMEUNIT.PCMBYTES);

update
mouseDeltaY = OldMouseY – mouseStartY;

channelDesiredPos = (int)channelStartPos + (mouseDeltaY * samplesPerPixel);

// calculate the delta of current and desired channel position
channelDeltaPos = (int)channelStartPos – channelDesiredPos;

// set a frequency value that will move the channel in the right direction
channelFreq = channelDefaultFreq * (channelDeltaPos * X);
channel.setFrequency(channelFreq);

OldMouseY = mouseStartY;
[/code:5me8qktp]

MouseDown e MouseMove are to be equal cause when you move the mouse (with the button pressed) and then stop you have to start everything from the beginning.

I also tried to set the position instead of changing the channel frequency:

[code:5me8qktp]

update
mouseDeltaY = OldMouseY – mouseStartY;

channelDesiredPos = (int)channelStartPos + (mouseDeltaY * samplesPerPixel);

// calculate the delta of current and desired channel position
channelDeltaPos = (int)channelStartPos – channelDesiredPos;

channel.setPosition((uint)channelDesiredPos, FMOD.TIMEUNIT.PCMBYTES);
[/code:5me8qktp]

but its the same: the channel position doesnt correspond to the mouse position.

It seems that when I go backword with the mouse the update works somewhat in a different way. I even tried to pause the channel (set the frequency to 0) but its the same.

Can someone help me?

  • You must to post comments
0
0

A friend of mine suggested me this method:

The ideal method would be, rather than use the "Play" functionality of fmod, pull the sample data manually and push to a sound object.
you could then control the sound much better. would simple be a case of pulling data earlier in stream ( as done by the commercial apps). again buffering would be better as pulling data from disk would be too slow.

what do you think about this?

  • You must to post comments
0
0

hi djmiky,

That does sound like an optimal solution, but it would be a lot of work. You’re basically taking on the resampling yourself.

Some things you might like to look at to get started would be:

FMOD::Sound::lock/unlock, this gives you access to the raw sound data of a sound file.

You can use FMOD_CREATESOUNDEXINFO pcmreadcallback to create a sound object that will play custom sound data. That callback will be hit when ever FMOD’s mix thread needs more data, you can fill that buffer with whatever you want.

Let me know how it goes,

-Pete

  • You must to post comments
0
0

hi paul,
yes this is an optimal solution but in this way FMOD becomes nearly unuseful…

what do you think about the code I have used?

even the code I have used to set the position instead of changing the channel frequency doesnt work how it should…
I cant understand why!

  • You must to post comments
0
0

Having a look at the latest code you posted:

[b:2kk0hd37]MouseMove[/b:2kk0hd37]
Mine:
[code:2kk0hd37]mouseDeltaY = mouseStartY – mouseCurrentY
channelDesiredPos = channelStartPos + (mouseDeltaY * samplesPerPixel) [/code:2kk0hd37]
Yours:
[code:2kk0hd37]mouseStartY = currentMouseY;
channel.getPosition(ref channelStartPos, FMOD.TIMEUNIT.PCMBYTES); [/code:2kk0hd37]

In my example mouseStartY represented the location of the cursor when the mouse down event occured. It should not be changed in mouse move event. Mine works by calculating the delta from that mouseStart position to the current position. Rather than a delta since last update, it’s a delta since the MouseDown event. This gives you the absolute difference rather than a relative difference. This method works by calculating what that expected channel position would be, then setting the frequency to move the channel toward that position.

EXAMPLE:

MouseDown
mouseStartY = 100

MouseMove
mouseCurrentY= 110
mouseDeltaY = 100 – 110 = -10

[next we would calculate where the channel position should be then set the frequency to a value that is going to move the channel toward that desired position]

MouseMove
mouseCurrent = 80
mouseDeltaY = 100 – 80 = 20

[now we have moved 30 pixels back past the original mouse down position so we recalculate our expected channel position and set the frequency to a value that will move it closer to the new desired channel position.]

Hope this helps,

-Pete

  • You must to post comments
0
0

in this way there is a problem when you move and then stop the mouse after the mouse down event.

Example:

MouseDown
mouseStartY = 100

MouseMove
mouseCurrentY= 110
mouseDeltaY = 100 – 110 = -10

Now if you stop moving the mouse the channel frequency grows up every update call (cause mouseDeltaY != 0 ) insted to be set to 0.
for this reason is needed to update the channel position in mousemove event, too.

  • You must to post comments
Showing 12 results
Your Answer

Please first to submit.