|
tmighty
Posts: 27
|
 |
« on: 14 Jan '06 - 17:30 » |
Quote
|
Hello again! I am a step further, but I still have a question please: I am checking the volume of mic-input in RecordProc-Callback. My question is: Shall I call BASS_ChannelGetLevel(chan) in the RecordProc function or can I see the volume in the "buffer"-data? If I can get it from the buffer data, how do I get the volume from it? I am a VB6 programmer, so I won't be able to understand C oder Delphi or so, because data types are completely different in these languages. But if someone knows how to get the volume in VB6 without calling GetLevel then it would be very nice. I think calling GetLevel is just to slow, right? Thank you! Tmighty.
|
|
|
|
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #1 on: 14 Jan '06 - 20:40 » |
Quote
|
http://www.un4seen.com/forum/?topic=4804.msg32055#msg32055That code would probably look like this in VB (quick and non-tested code): Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal length As Long)
Dim maxL As Single, maxR As Single Dim b() As Single ReDim b(length / 4) As Single maxL = 0.0: maxR = 0.0 Dim l4 As Long, a As Long l4 = length / 4
CopyMemory b(0), ByVal buffer, length
For a = 0 To (length / 4) - 1 If (a Mod 2) = 0 Then If b(a) > maxL Then maxL = b(a) Else If b(a) > maxR Then maxR = b(a) End If Next a
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #2 on: 14 Jan '06 - 21:29 » |
Quote
|
Thank you very much for your code. I have changed Single to Long and now it works very good I think! Dim maxL As Long, maxR As Long Dim b() As Long ReDim b(length / 4) As Long maxL = 0#: maxR = 0# Dim l4 As Long, a As Long I have encountered a memory error which is likely to be VB6's fault and I have seen a thread with a way around it. TM.
|
|
|
|
« Last Edit: 14 Jan '06 - 21:44 by tmighty »
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #3 on: 14 Jan '06 - 23:32 » |
Quote
|
Thank you very much for your code. I have changed Single to Long and now it works very good I think!
It depends if you specified BASS_SAMPLE_FLOAT in the BASS_RecordStart call. If you have, BASS will "send" floating-point data to your callback, and you should use a Single data type to get correct sample values. If not, Integer/Long will be fine as BASS defaults to 16-bit if neither BASS_SAMPLE_8BITS or BASS_SAMPLE_FLOAT is specified. Just a little explanation. 
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #4 on: 15 Jan '06 - 00:04 » |
Quote
|
Hi and thanks for answering! I am so confused about all the Pointers and stuff and I still have a big problem: Every time I do something that forces VB to do something in the RecordProc it crashes down with an exception error of the memory kind. Can you please tell me if this is the known callback safety problem or am I doing something very wrong? For example: If am checking the volume while in the RecordProc function -> It crashes with the memory error... I am confused, desperate and angry... Thank you for your help! Tmighty.
|
|
|
|
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #5 on: 15 Jan '06 - 00:43 » |
Quote
|
Well, did you find out where it's crashing? I just wrapped up a quick test based on the DSPTEST example, and it worked fine (it atleast returned maxL/R values). Post your "RecordProc" callback.
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #6 on: 15 Jan '06 - 01:37 » |
Quote
|
Hello. This is my callback code: Public Function RECORDPROC(ByVal handle As Long, ByVal buffer As Long, ByVal length As Long, ByVal user As Long) As Long
Dim maxL As Long, maxR As Long Dim b() As Long ReDim b(length / 4) As Long maxL = 0#: maxR = 0# Dim l4 As Long, a As Long l4 = length / 4
CopyMemory b(0), ByVal buffer, length
For a = 0 To (length / 4) - 1 If (a Mod 2) = 0 Then If b(a) > maxL Then maxL = b(a) Else If b(a) > maxR Then maxR = b(a) End If Next a
Debug.Print maxR
End Function
And this is how I start the initializing and recording: Public Sub StartEverything()
'change and set the current path 'so VB won't ever tell you that bass.dll isn't found ChDrive App.Path ChDir App.Path
'check if bass.dll is exists If (Not FileExists(RPP(App.Path) & "bass.dll")) Then Call MsgBox("BASS.DLL does not exists", vbCritical, "BASS.DLL") End End If
'Check that BASS 2.2 was loaded If (BASS_GetVersion <> MakeLong(2, 2)) Then Call MsgBox("BASS version 2.2 was not loaded", vbCritical, "Incorrect BASS.DLL") End End If
'initialize BASS recording (default device) If (BASS_RecordInit(-1) = 0) Then MsgBox "Can't initialize device" End End If
'start recording (44100hz mono 16-bit) chan = BASS_RecordStart(44100, 1, 0, AddressOf RECORDPROC, 0) If chan = 0 Then MsgBox "Can't start recording" End End If
'///////////////////////////////////////////////////////////////////////////////////// 'This is the code of the LiveSpectrum, which I wanted to have within my app
specpos = 0 specmode = False SPECWIDTH = 368 SPECHEIGHT = 127
'create bitmap to draw spectrum in - 8 bit for easy updating :) With bh.bmiHeader .biSize = Len(bh.bmiHeader) .biWidth = SPECWIDTH .biHeight = SPECHEIGHT 'upside down (line 0=bottom) .biPlanes = 1 .biBitCount = 8 .biClrUsed = 256 .biClrImportant = 256 End With
Dim a As Byte
'setup palette For a = 1 To 127 bh.bmiColors(a).rgbGreen = 255 - 2 * a bh.bmiColors(a).rgbRed = 2 * a Next a For a = 0 To 31 bh.bmiColors(128 + a).rgbBlue = 8 * a bh.bmiColors(128 + 32 + a).rgbBlue = 255 bh.bmiColors(128 + 32 + a).rgbRed = 8 * a bh.bmiColors(128 + 64 + a).rgbRed = 255 bh.bmiColors(128 + 64 + a).rgbBlue = 8 * (31 - a) bh.bmiColors(128 + 64 + a).rgbGreen = 8 * a bh.bmiColors(128 + 96 + a).rgbRed = 255 bh.bmiColors(128 + 96 + a).rgbGreen = 255 bh.bmiColors(128 + 96 + a).rgbBlue = 8 * a Next a
'update timer 25ms (40hz) MainForm.tmrLiveSpec.Enabled = True End Sub Thank you for your help. It always crashes, sometimes even if I only do something like: Public Function RECORDPROC(ByVal handle As Long, ByVal buffer As Long, ByVal length As Long, ByVal user As Long) As Long
dim myNumber% myNumber = 1 myNumber = myNumber+1
End Function
Thanks again. Tm.
|
|
|
|
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #7 on: 15 Jan '06 - 13:41 » |
Quote
|
You're getting a crash because you're attempting to loop through stereo samples. length / 4
This is the same as length / 2 (sample byte size, 16/8) / 2 (stereo, 2 channels). I noticed you're recording in mono, so length / 4 has to be length / 2. I've uploaded an example for you to have a look at. http://www.un4seen.com/filez/2/volume.zip
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #8 on: 15 Jan '06 - 14:40 » |
Quote
|
Thank you very much! I have noticed the following: VB users should not or can not test their applications within the ide/ debugmode or they will be getting crahes (also in your very kind sample extra written for me!) There is this safecallback.dll, but it doesn't help in my case, application still crashes if not compiled. But: If the project is being run as a compiled exe, it works fine (at last on my computer). So this is a bit of a pitty, and I would like to know why this is so and what I can do to prevent this. A question for the PROs: Is it the same as with the HighResolution Media Timers where the timer fires faster than VB can process it? Thanks for all the help so far again! TM.
|
|
|
|
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #9 on: 15 Jan '06 - 14:51 » |
Quote
|
It could be due to BASS being multithreaded, and VB isn't. I'm never running my applications in the VB IDE unless a VB run-time error occurs and I can trace it in my code.
|
|
|
|
|
Logged
|
|
|
|
|
(: JOBnik! :)
Posts: 991
|
 |
« Reply #10 on: 15 Jan '06 - 15:07 » |
Quote
|
Hi  VB is very sensitive and always crashes if using a debugging in IDE mode (using CALLBACKS). Multimedia Timer will sometimes crash in IDE and sometimes in Compiled modes, but will always crash in IDE DEBUG as it uses a CALLBACK function, the same with a simple API timer. There might be a crash if your CPU has HT as well, as VB doesn't has support for it.
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #11 on: 15 Jan '06 - 15:13 » |
Quote
|
! Oh yes !  I'm getting there!! VB hasn't crashed for 5 minutes now!!! Maybe it really was because of the "4" thingy which you have corrected to "2"...
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #12 on: 15 Jan '06 - 16:01 » |
Quote
|
Okay, everything's fine so far, except that I wanted to call BassEnc in RECORDPROC if maxL is over my threshhold level.  What I did was: Public Function RECORDPROC(ByVal handle As Long, ByVal buffer As Long, ByVal length As Long, ByVal user As Long) As Long
RECORDPROC = BASSTRUE
Dim maxL As Long, maxR As Long Dim b() As Integer ReDim b(length / 2) As Integer maxL = 0: maxR = 0 Dim l2 As Long, a As Long l2 = length / 2
CopyMemory b(0), ByVal buffer, length
For a = 0 To l2 - 1 If (a Mod 2) = 0 Then If b(a) > maxL Then maxL = b(a) Else If b(a) > maxR Then maxR = b(a) End If Next a
iLevel = maxR
If iLevel > 20000 Then If bEncoding = False Then 'If not already encoding bStartEncoding = True 'remember than encoding shall start Call DoBassEncStartEncoding 'call the sub that starts encoding End If End If End Function
And the "DoBassEncStartEncoding" looks like this: Public Sub DoBassEncStartEncoding()
If bEncoding = True Then Exit Sub 'Encoding already started, so exit! If bStartEncoding = True Then bStartEncoding = False'Remember that encoding was started
'free old recording If (chan) Then Call BASS_StreamFree(chan) chan = 0 MainForm.btnPlay.Enabled = False End If
'Start recording @ 44100hz 16-bit stereo (paused to add encoder first) rchan = BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, AddressOf ENCODEPROC, 0)
'Set command-lines and output files commands(1) = "lame.exe --alt-preset standard - bass.mp3" ' lame (MP3) files(1) = "bass.mp3"
'start encoding 'get selected encoder (0=OGG, 1=MP3) encoder = 1
'(Some error handling which I delete for better reading)
'resume recoding Call BASS_ChannelPlay(rchan, BASSFALSE) MainForm.btnRecord.Caption = "Stop" End Sub
Every time this "DoBassEncStartEncoding" is started it gives me a bad "memory read" error. Can you tell me what is wrong with my code? Oh I forgot the purpose: Every time a certain level from the Mic-Input is received it shall start encoding a phrase from the Mic to mp3. The end of the phrase will be checked in the ENCODEPROC function. Thanks. Tm.
|
|
|
|
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #13 on: 15 Jan '06 - 16:54 » |
Quote
|
Do you want to overwrite the MP3 file everytime the threshold level has been reached? If not, you're better off using an EncodeProc and appending the encoded sample data to the MP3 file.
Edit:
I can't see any call to BASS_Encode_Start. Did you post the complete "DoBassEncStartEncoding" procedure?
|
|
|
|
« Last Edit: 15 Jan '06 - 17:21 by Sebastian Andersson »
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #14 on: 15 Jan '06 - 17:23 » |
Quote
|
This is something I did not include: The name of the mp3 is being received from somewhere else, so there's no chance of overwriting. I just did not include that piece of code... Can you help with the crash, anyways? Is there something terribly wrong? I need to keep that one channel (=chan) for displaying a spectrum. So there is no problem in defining just another channel for encoding (=rchan), right? Greetings, TM.
|
|
|
|
« Last Edit: 15 Jan '06 - 17:26 by tmighty »
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #15 on: 15 Jan '06 - 17:25 » |
Quote
|
Well, yes, if you include the call to BASS_Encode_Start, I might wrap up an example and see if it crashes on my side.
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #16 on: 15 Jan '06 - 17:29 » |
Quote
|
It's just the function from the BassEnc.dll!
I have quoted the sub that calls this Function in the last post.
Declare Function BASS_Encode_Start Lib "bassenc.dll" (ByVal chan As Long, ByVal cmdline As String, ByVal flags As Long, ByVal proc As Long, ByVal user As Long) As Long
Sorry, our posts got mixed up. You were too quick! Hope it's all still understandable!
|
|
|
|
« Last Edit: 15 Jan '06 - 17:31 by tmighty »
|
Logged
|
|
|
|
|
Sebastian Andersson
Posts: 372
|
 |
« Reply #17 on: 15 Jan '06 - 17:48 » |
Quote
|
Yes, but you have to call it to start encoding. Are you actually doing that?
|
|
|
|
|
Logged
|
|
|
|
|
tmighty
Posts: 27
|
 |
« Reply #18 on: 15 Jan '06 - 18:41 » |
Quote
|
Oh sorry, I deleted it (only in my posting, not in my actual code). The real code I'm using is: 'get selected encoder (0=OGG, 1=MP3) encoder = 1
If (BASS_Encode_Start(rchan, commands(encoder), 0, 0, 0) = 0) Then Call Error_("Couldn't start encoding..." & vbCrLf & _ "Make sure OGGENC.EXE (if encoding to OGG) is in the same" & vbCrLf & _ "direcory as this RECTEST, or LAME.EXE (if encoding to MP3).") Call BASS_ChannelStop(rchan) rchan = 0 End Exit Sub End If
'resume recoding Call BASS_ChannelPlay(rchan, BASSFALSE)
I don't know what's still wrong 
|
|
|
|
|
Logged
|
|
|
|
|
Ian @ un4seen
Administrator
Posts: 15366
|
 |
« Reply #19 on: 15 Jan '06 - 19:14 » |
Quote
|
I'd suggest you start with simply using BASS_ChannelGetLevel, as in this thread. Once you get that working, then you could try scanning the level yourself. Note though that BASS_ChannelGetLevel is pretty quick, and will almost certainly be faster than scanning the level yourself, particularly in VB  Btw, it appears that you're recording twice from the device - once just to scan the level, and again to record/encode. Note that will only work on XP. I'm not sure you really want (or need  ) to do that. Also, as you're dealing with mono sample data, there's no need to have separate maxL/maxR readings when scanning the data.
|
|
|
|
|
Logged
|
|
|
|
|