|
AndyMK
Posts: 171
|
 |
« on: 26 Apr '09 - 19:26 » |
Quote
|
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  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 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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 
|
|
|
|
« Last Edit: 30 Apr '09 - 02:21 by AndyMK »
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #8 on: 30 Apr '09 - 08:43 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 
|
|
|
|
|
Logged
|
|
|
|
|
AndyMK
Posts: 171
|
 |
« Reply #12 on: 30 Apr '09 - 15:10 » |
Quote
|
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 » |
Quote
|
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  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 » |
Quote
|
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  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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
Opps sorry Bernd, posted to quick... Well maybe a C# example then.. 
|
|
|
|
|
Logged
|
|
|
|
|
AndyMK
Posts: 171
|
 |
« Reply #18 on: 4 May '09 - 17:46 » |
Quote
|
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 » |
Quote
|
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
|
|
|
|
|