24 May '13 - 08:01 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1] 2 3  All
  Reply  |  Print  
Author Topic: Vynil Scratching Demo  (Read 10198 times)
AndyMK
Posts: 171


« on: 26 Apr '09 - 19:26 »
Reply with quoteQuote

Hi all, i managed to get the basic scratching sound that a few people are looking for. I have included a !!very!! basic demo. i need to smooth a few values and tweak the stop start spin stuff but its a start Smiley I have a 2 deck version with headphone cue and fader all working. EQ is going in now and interface has started.

This Demo:

Asio only
Uses first asio driver in the list
Rear outs disabled

1. double click an mp3 in the browser to play
2. left slider = pitch
3. right slider = volume
4. left click hold and move on godfather to scratch
5. left click hold with right click to set cue point
6. right click to play from cue point
7. mouse wheel up = nudge up
8. mouse wheel down = nudge down

Have fun Smiley

http://www.uploadfile.ws/files/get/zV-wYUT1oy/scratchdemo.zip

« Last Edit: 26 Apr '09 - 19:54 by AndyMK » Logged
muntablues
Posts: 191


« Reply #1 on: 29 Apr '09 - 11:43 »
Reply with quoteQuote

Hi Andy

Iīve testet your demo and I have to say, itīs a great start!!!

Is this soft written in PureBasic or which language did you use? Could you give us/me a hint how to calculate the scratch effect, that would be great.

As I can hear it you change the sample rate and the direction and that very fast, is that right?

Do you use Bass to decode the channel, get data and manipulate it and then you send it to ASIO, right or wrong?
 
I know many questions but it would be great if you could explain it a little bit.

Thanks you very much!!!

MB
Logged
AndyMK
Posts: 171


« Reply #2 on: 29 Apr '09 - 16:30 »
Reply with quoteQuote

Hi muntablues, It was all done in Purebasic. The graphics engine is PureGDK which is Darkbasic Pro in dll form. Everything in BASS is a decoding channel apart from the asio outputs of course. The scratching effect is done by calculating the angle of the mouse pointer from the center of the wheel and multiplying that angle by a number to get it into the thousands so that this value can be used as the sample rate of the decoding channel. When the the mouse moves clockwise, the sample rate value increases and this value is used to control BASS_ATTRIB_FREQ on the source channel. Again if the wheel is moved anticlockwise, the value is still positive and increases like before but now the channel is set in reverse (cant use negative sample rates). If this is nor clear i can post some code to explain it. The other important factor is that you must interpolate(smooth) the angle value as it is being generated otherwise the frquency slide sounds choppy or not very uniform.
Logged
radio42
Posts: 4012


« Reply #3 on: 29 Apr '09 - 16:38 »
Reply with quoteQuote

Hi Andy,

yes, some code fragments would be great. Especially the FREQ resp. angle calculation and the smoothing.
Great demo!
Logged
muntablues
Posts: 191


« Reply #4 on: 29 Apr '09 - 16:48 »
Reply with quoteQuote

Yes yes and yes. The calculation would be great!!!

Thanks a lot.

MB
Logged
AndyMK
Posts: 171


« Reply #5 on: 29 Apr '09 - 16:59 »
Reply with quoteQuote

Here is the complete source code to the demo, its written in purebasic but it shouldnt be too hard to convert. The only thing i cant explain is the interpolation because i used a command that done it for me but what you could do is use the BASS slide commands to do the same thing. i might use them myself as they seem to produce smoother results.

timeBeginPeriod_(1)
IncludeFile "bass.pbi"
IncludeFile "bass_fx.pbi"
IncludeFile "bassmix.pbi"
IncludeFile "bassasio.pbi"

Global w = 540
Global h = 500
Global addr.s
Global addr1.s
Global Quit
Global Thresh.f = 2
Global Mixer

youx = 270
youy = 250
vol.f = 0.5
a.f = 0
b.f = 0
cuepos.q
rspeed.f = 2.5
Dim Matrix1.f(3, 1)

Procedure ListView(val)
  OpenWindow(1, 0, h-150, w, 150, "DJ GUI", #Null, WindowID(0))
  SetWindowColor(1, RGB(0, 0, 0))
  ExplorerListGadget(0, 0, 0, w, 150, "*.mp3", #PB_Explorer_BorderLess | #PB_Explorer_AutoSort)
  SetGadgetColor(0, #PB_Gadget_FrontColor, RGB(255, 255, 255))
  SetGadgetColor(0, #PB_Gadget_BackColor, RGB(0, 0, 0))
  SetGadgetAttribute(0, #PB_Explorer_DisplayMode, #PB_Explorer_List)
  SetGadgetItemAttribute(0, 0, #PB_Explorer_ColumnWidth, 300)
  Repeat
    Delay(1)
    Event = WaitWindowEvent()
    EventType = EventType()
    If EventType = #PB_EventType_LeftDoubleClick
      Path.s = GetGadgetText(0)
      File.s = GetGadgetItemText(0, GetGadgetState(0))
      addr.s = Path + File
    EndIf
  Until Quit = 1
EndProcedure

Procedure Deck1BoostDSP(Handle, Channel, Buffer, Lenght, User)
 
  For i = 0 To Lenght-1 Step 8
   
    Channel1.f = PeekF(Buffer + i)*Thresh
    Channel2.f = PeekF(Buffer + i + 4)*Thresh
   
    If Channel1> = 1 Or Channel2> = 1 Or Channel1< = -1 Or Channel2< = -1
      Thresh = Thresh-0.01
     
      If Channel1> = 1
        Channel1 = 0.99
      EndIf
      If Channel2> = 1
        Channel2 = 0.99
      EndIf
     
      If Channel1< = -1
        Channel1 = -0.99
      EndIf
      If Channel2< = -1
        Channel2 = -0.99
      EndIf
    Else
      Thresh = Thresh + 0.000001
    EndIf
   
    PokeF(Buffer + i, Channel1)
    PokeF(Buffer + i + 4, Channel2)
   
  Next
 
EndProcedure

Procedure ASIOPROC(Input, Channel, Buffer, Length, User)
  j = BASS_ChannelGetData(Mixer, Buffer, Length)
  If j = -1
    j = 0
  EndIf
  ProcedureReturn j
EndProcedure

OpenWindow(0, 0, 0, w, h, "Scratch Demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
hDBWnd = OpenDBWnd(WindowID(0), 0, 0, w, h)
dbSetDisplayMode(w, h, 1, 0, 0)
dbSyncRate(0)
dbInk(dbRGB(255, 255, 255), dbRGB(0, 0, 0))
dbSetDir("Media")
dbSetImageColorkey(255, 255, 255)
dbLoadImage("The_Godfather.bmp", 1)
dbLoadImage("linemarks2.bmp", 3)
dbLoadImage("linemarks.bmp", 4)
dbLoadImage("slider2.bmp", 6)

dbSprite(3, 366, 58, 3)
dbSprite(4, 50, 58, 4)

dbSprite(1, 270, 250, 1)
dbOffsetSprite(1, 190, 190)
dbScaleSprite(1, 90)

dbSprite(9, 270, 250, 6)
dbOffsetSprite(9, 235, 10)

dbSprite(13, 270, 250, 6)
dbOffsetSprite(13, 235, 10)
dbRotateSprite(13, 180)

BASS_Init(0, 44100, #Null, WindowID(0), #Null)
BASS_ASIO_Init(0)
BASS_ASIO_SetRate(44100)
BASS_ASIO_ChannelEnable(#False, 0, @ASIOPROC(), 0)
BASS_ASIO_ChannelSetFormat(#False, 0, #BASS_ASIO_FORMAT_FLOAT)
BASS_ASIO_ChannelJoin(#False, 1, 0)
BASS_ASIO_Start(512)
Mixer = BASS_Mixer_StreamCreate(44100, 2, #BASS_SAMPLE_FLOAT | #BASS_STREAM_DECODE)
Thread = CreateThread(@ListView(), 0)

Repeat
  dbCLS()
  Event = WindowEvent()
  EventType = EventType()
  ActiveWindow.l = GetActiveWindow()
  MouseX = dbMouseX()
  MouseY = dbMouseY()
  targetx = MouseX : targety = MouseY
 
  OldAngle.f = NewAngle.f
  dx = targetx-youx : dy = targety-youy
  NewAngle = 180-dbATanFull(dx, dy)
 
  If NewAngle-OldAngle<-180 Or NewAngle-OldAngle>180
   
a = dbCurveValue((360-NewAngle-OldAngle), a, 4) ; <--- interpolate the value over 4ms period assuming vsync is enabled @ 60hz (60hz = 16.6ms delay per loop so the 4ms value is not really 4ms) This is the FREQ value.

    b = a*10000
  Else
    a = dbCurveValue((NewAngle-OldAngle), a, 4)
    b = a*10000
  EndIf
 
  Distance1 = Sqr((MouseX-youx)*(MouseX-youx) + (MouseY-youy)*(MouseY-youy))
 
  num.f = dbCurveValue(mmz*100, num, 10) ; <--- same principal here but interpolate over 10ms for the nudging of the audio
 
  If addr<>""
    If BASS_ChannelIsActive(Source) = #BASS_ACTIVE_PLAYING
      BASS_ChannelRemoveDSP(Source, Deck1Boost)
      BASS_StreamFree(Source)
    EndIf
   
    Source = BASS_StreamCreateFile(#False, @addr, 0, 0, #BASS_STREAM_DECODE | #BASS_SAMPLE_FLOAT | #BASS_STREAM_PRESCAN)
    Source = BASS_FX_ReverseCreate(Source, 1, #BASS_STREAM_DECODE)
    BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
    Deck1Boost = BASS_ChannelSetDSP(Source, @Deck1BoostDSP(), 0, 0)
    BASS_Mixer_StreamAddChannel(Mixer, Source, #BASS_MIXER_MATRIX | #BASS_MIXER_NORAMPIN)
   
    Matrix1(0, 0) = vol ;Front Left
    Matrix1(1, 1) = vol ;Front Right
   
    BASS_Mixer_ChannelSetMatrix(Source, @Matrix1())
   
    Thresh = 2
    addr = ""
  EndIf
 
  If ActiveWindow<>-1
   
    Select dbMouseClick()
       
      Case 1
        If Distance1<172
          If flag = 0
            flag = 1
            Deck = 1
          EndIf
        EndIf
       
        If Distance1<225 And Distance1>185 And MouseX<270
          If flag = 0
            flag = 1
            Pitch = 1
          EndIf
        EndIf
       
        If Distance1<225 And Distance1>185 And MouseX>270
          If flag = 0
            flag = 1
            Volume = 1
          EndIf
        EndIf
       
        If Deck = 1
          If b>100
            dbRotateSprite(1, dbSpriteAngle(1) + a)
            If rev = 1
              rev = 0
              BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
            EndIf
            BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, b)
          EndIf
         
          If b<-100
            dbRotateSprite(1, dbSpriteAngle(1) + a)
            If rev = 0
              rev = 1
              BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_REVERSE)
            EndIf
            BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, -b)
          EndIf
        EndIf
       
        If Volume = 1
          dbRotateSprite(13, dbSpriteAngle(13) + a)
          vol = (240-dbSpriteAngle(13))*0.00833
          Matrix1(0, 0) = vol ;Front Left
          Matrix1(1, 1) = vol ;Front Right
          BASS_Mixer_ChannelSetMatrix(Source, @Matrix1())
        EndIf
       
        If Pitch = 1
          dbRotateSprite(9, dbSpriteAngle(9) + a)
          PitchVal = dbSpriteAngle(9)*50
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
        EndIf
       
      Case 2
        dbRotateSprite(1, dbSpriteAngle(1) + rspeed)
       
        If Distance1<172
          If flag = 0
            flag = 1
            BASS_ChannelSetPosition(Source, cuepos, #BASS_POS_BYTE)
          EndIf
        EndIf
       
      Case 3
        If Deck = 1
          cuepos = BASS_ChannelGetPosition(Source, #BASS_POS_BYTE)
        EndIf
       
      Default
        flag = 0
        Deck = 0
        Fader = 0
        Pitch = 0
        Volume = 0
       
        dbRotateSprite(1, dbSpriteAngle(1) + rspeed)
       
        If rev = 1
          rev = 0
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
        Else
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
        EndIf
       
        If Distance1<172
          mmz = dbMouseMoveZ()
         
BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal + num) <-- num was num2 in the demo exe so the nudging probably didnt work.

        EndIf
       
    EndSelect
  EndIf
 
  dbText(0, 480, StrF(Thresh))
 
  dbFastSync()
 
Until Event = #PB_Event_CloseWindow
Quit = 1
BASS_Free()
BASS_ASIO_Free()
timeEndPeriod_(1)
End

If there are things in the code you need explaining just ask, i didnt have time to comment the code, i tend to do it all in my head.

Deck1BoostDSP is a basic volume normalizer.

Fixed exe with working nudge just so you can hear what its doing when looking at the code.
http://www.uploadfile.ws/files/get/mBHIMDpJAZ/scratchdemonudgefix.zip

« Last Edit: 29 Apr '09 - 17:24 by AndyMK » Logged
muntablues
Posts: 191


« Reply #6 on: 29 Apr '09 - 22:11 »
Reply with quoteQuote

Hi all

Some time ago (about one year) I tried to implement something like scratching. Now I see this code and there is nearly the same what I was doing. The real big difference is that Andy is using a buffer to get the audio data.

Iīve tried it myself now, but it is quick and dirty and not with ASIO. The scratching is not as fine as in Andys demo but you can here there is something scratching.

BUT I have one big problem.

Switching the direction is really slow. I guess there is a problem with the internal buffer. There is a delay of 200-300ms to switch between forward and reverse. Is there something going wrong or is it maybe a problem of bassfx? I have tried to change only the direction but the delay is still there.

This is what I do.

Create FileStream (decode) -> Create ReverseStream (decode) -> Create TempoStream (speaker) -> Play TempoStream

Manipulation:
       
        public void ScratchTo(float freq, int time, bool reverse)
        {
            if (freq > channel_info.freq *2)
                freq = channel_info.freq * 2;
            if (!reverse)
            {
                Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, 1f);
                Bass.BASS_ChannelSlideAttribute(stream_tempo, BASSAttribute.BASS_ATTRIB_FREQ, freq, time);
            }
            else
            {
                bool ok = Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, (float)BASSFXReverse.BASS_FX_RVS_REVERSE);
                Bass.BASS_ChannelSlideAttribute(stream_tempo, BASSAttribute.BASS_ATTRIB_FREQ, freq, time);
            }
        }

Maybe there is someone out there who can help me out.

Thanks MB
Logged
AndyMK
Posts: 171


« Reply #7 on: 30 Apr '09 - 01:47 »
Reply with quoteQuote

Take out the tempostream unless you plan on timestretching, otherwise send the reverse stream to the speakers. during your reverse point you need to stop the stream, reverse it then start it (has to be done for directsound.. something to do with flushing the output buffer before starting playback in reverse). If you set your bass config buffer to anything lower than 100ms it will be similar to what my demo is doing. the reason i went for asio is because i needed everything instant or as close as poss. Things like eq and fx would have had at least 30ms delay and that was not good enough for what i wanted. Asio also seems easier to use and considering most soundcards support it through the Asio4all driver, i thought why not Smiley
« Last Edit: 30 Apr '09 - 02:21 by AndyMK » Logged
radio42
Posts: 4012


« Reply #8 on: 30 Apr '09 - 08:43 »
Reply with quoteQuote

Yes, I made the same experiance.
Adding a tempo streams adds to much delay, so that the sound can not follow the mouse movement quick enough while 'scratching'.
The same goes with DirectSound as here the output also lags to much behing the 'scratching'.
Logged
muntablues
Posts: 191


« Reply #9 on: 30 Apr '09 - 11:29 »
Reply with quoteQuote

So you think there is no possibility to make it with DirectSound. My users will not be very happy about that, althought there is the solution with ASIO2ALL.

I think I will try to stop the channel if the direction is changing and start it again. Maybe its enough for me.

By the way, my buffer is allready at 150ms, that is at least the lowest value which works fine. But as you said EQ and FX causes 30ms so there will be no other solution than using ASIO.

So on,

MB

 
Logged
Ian @ un4seen
Administrator
Posts: 15270


« Reply #10 on: 30 Apr '09 - 14:28 »
Reply with quoteQuote

Switching the direction is really slow. I guess there is a problem with the internal buffer. There is a delay of 200-300ms to switch between forward and reverse. Is there something going wrong or is it maybe a problem of bassfx? I have tried to change only the direction but the delay is still there.

This is what I do.

Create FileStream (decode) -> Create ReverseStream (decode) -> Create TempoStream (speaker) -> Play TempoStream

Manipulation:
       
        public void ScratchTo(float freq, int time, bool reverse)
        {
            if (freq > channel_info.freq *2)
                freq = channel_info.freq * 2;
            if (!reverse)
            {
                Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, 1f);
                Bass.BASS_ChannelSlideAttribute(stream_tempo, BASSAttribute.BASS_ATTRIB_FREQ, freq, time);
            }
            else
            {
                bool ok = Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, (float)BASSFXReverse.BASS_FX_RVS_REVERSE);
                Bass.BASS_ChannelSlideAttribute(stream_tempo, BASSAttribute.BASS_ATTRIB_FREQ, freq, time);
            }
        }

Yep, the problem there is that the tempo/output stream will still have data buffered from before the direction switch. To avoid hearing that buffered data, you need to clear the output buffer, which can be done by seeking, eg. to the same position. You could try doing this after switching direction...

BASS_ChannelSetPosition(stream_tempo, BASS_ChannelGetPosition(stream_tempo, BASS_POS_BYTE), BASS_POS_BYTE);
Logged
AndyMK
Posts: 171


« Reply #11 on: 30 Apr '09 - 14:31 »
Reply with quoteQuote

your eq and fx will have the same delay that your soundcard is set to so 150ms output buffer will delay eq and fx by 150ms.. volume also unless you are using the volume settings on the output channels themselves then that is instant. The reverse thing will work pretty well if you do the stop>reverse>play. Lets say you have a 1000ms output buffer, when you reverse if you don't stop first, you will end up playing the remaining buffer before you hear the reverse come in. The BASS_ChannelStop function will flush the output buffer so that when the reverse comes in, you immediately hear the result and you dont have to wait for the remainder of the buffer to play. Also, if you use BASS_ChannelUpdate before the BASS_ChannelPlay, it should reduce the delay further.

oops.. sorry ian i posted at the same time Smiley
Logged
AndyMK
Posts: 171


« Reply #12 on: 30 Apr '09 - 15:10 »
Reply with quoteQuote

Here is a Directsound version of the demo. I have included an exe so you can hear the difference. Although the soundcards output buffer is set 5000ms (yes 5 whole seconds of delay) and 5ms period, there is no real delay on reverse. It also seems to work without pausing now that i have re writen it lol!! It's still not as good as the asio version but it may be sufficient for your needs.

timeBeginPeriod_(1)
IncludeFile "bass.pbi"
IncludeFile "bass_fx.pbi"

Global w = 540
Global h = 500
Global addr.s
Global Quit

youx = 270
youy = 250
vol.f = 0.5
a.f = 0
b.f = 0
cuepos.q
rspeed.f = 2.5

Procedure ListView(val)
  OpenWindow(1, 0, h-150, w, 150, "DJ GUI", #Null, WindowID(0))
  SetWindowColor(1, RGB(0, 0, 0))
  ExplorerListGadget(0, 0, 0, w, 150, "*.mp3", #PB_Explorer_BorderLess | #PB_Explorer_AutoSort)
  SetGadgetColor(0, #PB_Gadget_FrontColor, RGB(255, 255, 255))
  SetGadgetColor(0, #PB_Gadget_BackColor, RGB(0, 0, 0))
  SetGadgetAttribute(0, #PB_Explorer_DisplayMode, #PB_Explorer_List)
  SetGadgetItemAttribute(0, 0, #PB_Explorer_ColumnWidth, 300)
  Repeat
    Delay(1)
    Event = WaitWindowEvent()
    EventType = EventType()
    If EventType = #PB_EventType_LeftDoubleClick
      Path.s = GetGadgetText(0)
      File.s = GetGadgetItemText(0, GetGadgetState(0))
      addr.s = Path + File
    EndIf
  Until Quit = 1
EndProcedure

OpenWindow(0, 0, 0, w, h, "Scratch Demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
hDBWnd = OpenDBWnd(WindowID(0), 0, 0, w, h)
dbSetDisplayMode(w, h, 1, 0, 0)
dbSyncRate(0)
dbInk(dbRGB(255, 255, 255), dbRGB(0, 0, 0))
dbSetDir("Media")
dbSetImageColorkey(255, 255, 255)
dbLoadImage("The_Godfather.bmp", 1)
dbLoadImage("linemarks2.bmp", 3)
dbLoadImage("linemarks.bmp", 4)
dbLoadImage("slider2.bmp", 6)

dbSprite(3, 366, 58, 3)
dbSprite(4, 50, 58, 4)

dbSprite(1, 270, 250, 1)
dbOffsetSprite(1, 190, 190)
dbScaleSprite(1, 90)

dbSprite(9, 270, 250, 6)
dbOffsetSprite(9, 235, 10)

dbSprite(13, 270, 250, 6)
dbOffsetSprite(13, 235, 10)
dbRotateSprite(13, 180)

BASS_Init(1, 44100, #BASS_DEVICE_SPEAKERS, WindowID(0), #Null)
BASS_SetConfig(#BASS_CONFIG_BUFFER, 5000)
BASS_SetConfig(#BASS_CONFIG_UPDATEPERIOD, 5)
Thread = CreateThread(@ListView(), 0)

Repeat
  dbCLS()
  Event = WindowEvent()
  EventType = EventType()
  ActiveWindow.l = GetActiveWindow()
  MouseX = dbMouseX()
  MouseY = dbMouseY()
  targetx = MouseX : targety = MouseY
 
  OldAngle.f = NewAngle.f
  dx = targetx-youx : dy = targety-youy
  NewAngle = 180-dbATanFull(dx, dy)
 
  If NewAngle-OldAngle<-180 Or NewAngle-OldAngle>180
    a = dbCurveValue((360-NewAngle-OldAngle), a, 4)
    b = a*10000
  Else
    a = dbCurveValue((NewAngle-OldAngle), a, 4)
    b = a*10000
  EndIf
 
  Distance1 = Sqr((MouseX-youx)*(MouseX-youx) + (MouseY-youy)*(MouseY-youy))
 
  num.f = dbCurveValue(mmz*100, num, 10)
 
  If addr<>""
    If BASS_ChannelIsActive(Source) = #BASS_ACTIVE_PLAYING
      BASS_StreamFree(Source)
    EndIf
   
    Source = BASS_StreamCreateFile(#False, @addr, 0, 0, #BASS_STREAM_DECODE | #BASS_SAMPLE_FLOAT | #BASS_STREAM_PRESCAN)
    Source = BASS_FX_ReverseCreate(Source, 1, #BASS_SPEAKER_FRONT)
    BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
    BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_VOL, vol)
    BASS_ChannelPlay(Source, 0)
    addr = ""
  EndIf
 
  If ActiveWindow<>-1
   
    Select dbMouseClick()
       
      Case 1
        If Distance1<172
          If flag = 0
            flag = 1
            Deck = 1
          EndIf
        EndIf
       
        If Distance1<225 And Distance1>185 And MouseX<270
          If flag = 0
            flag = 1
            Pitch = 1
          EndIf
        EndIf
       
        If Distance1<225 And Distance1>185 And MouseX>270
          If flag = 0
            flag = 1
            Volume = 1
          EndIf
        EndIf
       
        If Deck = 1
          If b>100
            dbRotateSprite(1, dbSpriteAngle(1) + a)
            If rev = 1
              rev = 0
              BASS_ChannelStop(Source)
              BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
              BASS_ChannelPlay(Source,0)
            EndIf
            BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, b)
          EndIf
         
          If b<-100
            dbRotateSprite(1, dbSpriteAngle(1) + a)
            If rev = 0
              rev = 1
              BASS_ChannelStop(Source)
              BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_REVERSE)
              BASS_ChannelPlay(Source,0)
            EndIf
            BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, -b)
          EndIf
        EndIf
       
        If Volume = 1
          dbRotateSprite(13, dbSpriteAngle(13) + a)
          vol = (240-dbSpriteAngle(13))*0.00833
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_VOL, vol)
        EndIf
       
        If Pitch = 1
          dbRotateSprite(9, dbSpriteAngle(9) + a)
          PitchVal = dbSpriteAngle(9)*50
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
        EndIf
       
      Case 2
        dbRotateSprite(1, dbSpriteAngle(1) + rspeed)
       
        If Distance1<172
          If flag = 0
            flag = 1
            BASS_ChannelSetPosition(Source, cuepos, #BASS_POS_BYTE)
          EndIf
        EndIf
       
      Case 3
        If Deck = 1
          cuepos = BASS_ChannelGetPosition(Source, #BASS_POS_BYTE)
        EndIf
       
      Default
        flag = 0
        Deck = 0
        Fader = 0
        Pitch = 0
        Volume = 0
       
        dbRotateSprite(1, dbSpriteAngle(1) + rspeed)
       
        If rev = 1
          rev = 0
          BASS_ChannelStop(Source)
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_REVERSE_DIR, #BASS_FX_RVS_FORWARD)
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
          BASS_ChannelPlay(Source,0)
        Else
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal)
        EndIf
       
        If Distance1<172
          mmz = dbMouseMoveZ()
          BASS_ChannelSetAttribute(Source, #BASS_ATTRIB_FREQ, 44100 + PitchVal + num)
        EndIf
       
    EndSelect
  EndIf
 
  dbFastSync()
 
Until Event = #PB_Event_CloseWindow
Quit = 1
BASS_Free()
timeEndPeriod_(1)
End

EXE Demo

http://www.megaupload.com/?d=SP0SINXS
« Last Edit: 30 Apr '09 - 15:49 by AndyMK » Logged
muntablues
Posts: 191


« Reply #13 on: 4 May '09 - 11:40 »
Reply with quoteQuote

Hi all

I have tested you DirectSound demo and there are "bad" clips. I think its because you stop the channel and play it again. I tried now to set the position to flush the buffer like Ian said and there are no clips. So Andy you could try it like that and it would sound much better.

The only thing which is not really great in my app, is the caluculation of the new Pitch/Freq values. Andy have got a timer or how do you calculate the exact speed up/down. Sorry for this question but i donīt really understand your PureBasic code  Huh

It would be great if you could give me a short explanation. Do you know min max values of BASS_ATTRIB_FREQ? If I go higher than 120000 it sounds quiet bad in my app.

Thank you again.

MB
Logged
AndyMK
Posts: 171


« Reply #14 on: 4 May '09 - 15:27 »
Reply with quoteQuote

Hi muntablues, when you say "bad clips" do you mean the click you hear if you go back and forth on the same spot? if thats the case then ramp the volume to zero quickly at that point. BASS_ChannelStop() does flush the buffers i believe. Anyway, if setting the position makes it sound much better then thats the way to go Smiley The reason i used stop in the directsound version is because i had a parallel stream going to the headphones and using setposition made the streams loose sync. The solution was to stop the streams first.

I dont use any timers as such because my gui library automatically sets vsync on the display. This makes my program loop at precisely 60 frames per second. If you want accurate loop timing i would sugest using

timeBeginPeriod_(1) ; windows normally has a message pump accuracy of 15ms, this sets your app to 1ms precision
;all your code
timeEndPeriod_(1)
end

The frequency values are smoothed or interpolated over a very short period of time so for example, if the frequency is currently at 44100 and you push the wheel forward, it would smoothly go from 44100 to say, 60000, filling all the values in between.
Logged
ken
Posts: 630


« Reply #15 on: 4 May '09 - 16:09 »
Reply with quoteQuote

It's a very good start on Vinyl scratching with BASS. Good work AndyMK!

> Bernd, I love to see it in Bass.NET

/Ken
Logged
radio42
Posts: 4012


« Reply #16 on: 4 May '09 - 16:50 »
Reply with quoteQuote

What should be added for BASS.NET?
AndyMK is just using all function which are already there!
Just his UI calculation might be specific - but BASS.NET is not a UI library...
Logged
ken
Posts: 630


« Reply #17 on: 4 May '09 - 17:24 »
Reply with quoteQuote

Opps sorry Bernd, posted to quick...

Well maybe a C# example then..  Smiley
Logged
AndyMK
Posts: 171


« Reply #18 on: 4 May '09 - 17:46 »
Reply with quoteQuote

I must admit, i had a nightmare figuring it out myself at the begining so here is what my train of thought was at the time. The first thing i done was defined the center point of the wheel. Next, i needed to rotate the sprite around that point. That was easy. I defined a default rotation speed for example, 33 revolutions per minute just like vynil although in my demo i dont think it is but this is just an example. So at 33 revolutions per minute (0.55 revs/sec), the frequency was 44100 or the default sample speed. If we slow the wheel down to 0.25 revs/sec, we know that 0.55 = 44100, work out what 0.25 would be and set the new frequency. 44100/0.55 = 80181. New frequency at 0.25 revs/sec is 80181*0.25 = 20045. At the same time you will want to go from 44100 to 20045 smoothly so it doesnt just drop to half the speed instantly. Interpolate the value over a time period of 10ms or something. I know this may not be the best explanation in the world but its difficult to explain without writing a novel. Note that the rotation code has nothing to do with the generated frequency values, that is all done based on the the mouse position and movement and angle of mouse pointer position to the centre point.
« Last Edit: 4 May '09 - 17:49 by AndyMK » Logged
muntablues
Posts: 191


« Reply #19 on: 4 May '09 - 20:51 »
Reply with quoteQuote

Hi Andy

I will go into your explanation and hope to get it done. It sound quiet simple but I know that it will be some work to do...

Till there best wishes!

MB
Logged
Pages: [1] 2 3  All
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines