Record a WAV file with BASS.dll

Post your working scripts, libraries and tools
User avatar
metacognition
Posts: 87
Joined: 22 Oct 2014, 05:57
Location: Alaska

Record a WAV file with BASS.dll

12 Jul 2017, 01:47

I might be several years too late for anyone who was excited about Bass.dll.

I never actually saw anyone do a successful record with bass.dll, there was input meters but nothing else. Below is a script to record to a wav file. Thanks Lexikos for your assistance over one of my hurdles.

Code: Select all

SetBatchLines, -1
#Persistent

Gui, Add, Button, x182 y99 w100 h30 gStartRecord, Start
Gui, Add, Button, x182 y149 w100 h30 gStopRecord, Stop
; Generated using SmartGUI Creator for SciTE
Gui, Show, w479 h379, Untitled GUI
return

GuiClose:
ExitApp


StartRecord:

Control, Disable, , Start

RecordCallback := RegisterCallback("RecordFunction" )

FileDelete, 0_test.wav

;//// WRITE WAV HEADER /////

file := fileopen("0_test.wav", "rw", CP1252)
file.write("RIFF    ") ; leave space for file size - 8

file.write("WAVEfmt ") ; Wave Container, 'fmt ' chunk, this takes up 8 bytes.

fmt_length = 0
numput(16, fmt_length, "UInt") ; 16 bytes, length of formatchunk in bytes
file.rawwrite(fmt_length, 4)

fmt_type = 0
numput(1,fmt_type, "UShort") ; format, 1 = PCM, linear aka non compressed
file.rawwrite(fmt_type, 2)

fmt_channels = 0
numput(2, fmt_channels, "UShort") ; 2 channels
file.rawwrite(fmt_channels, 2)

fmt_sample_rate = 0
numput(44100, fmt_sample_rate, "UInt") ; 44100 samples per second
file.rawwrite(fmt_sample_rate, 4)

fmt_byte_rate = 0
numput(176400, fmt_byte_rate, "UInt") ; bytes per second, 176400
file.rawwrite(fmt_byte_rate, 4)

fmt_blockalign=0		 
numput(4, fmt_blockalign, "UShort") ; NumChannels * BitsPerSample/8
file.rawwrite(fmt_blockalign, 2)

fmt_bitspersample=0		 
numput(16, fmt_bitspersample, "UShort") ; 16 bit resolution
file.rawwrite(fmt_bitspersample, 2)

file.write("data    ") ; this takes up 8 bytes. leave space to write in the size of data chunk.
datasize = 0

;////// WAV HEADER COMPLETE, MOSTLY ///////




;////// LOAD BASS AND START RECORDING  /////////
DllCall("LoadLibrary","str",A_ScriptDir "\bass.dll") 
DllCall(A_ScriptDir "\bass.dll\BASS_RecordInit", Int,-1)
DllCall(A_ScriptDir "\bass.dll\BASS_ErrorGetCode")
hrecord := DllCall(A_ScriptDir "\bass.dll\BASS_RecordStart", UInt, 44100, UInt, 2, UInt, 0, UInt, RecordCallback, UInt, 0)
return


StopRecord:
DllCall(A_ScriptDir "\bass.dll\BASS_ChannelStop", UInt,hrecord)

;///// BACK TO HEADER //////
file.seek(40)

data_datasize=0
numput(datasize, data_datasize, "UInt") ; little endian
file.rawwrite(data_datasize, 4)

datasize+=36

file.seek(4)

riff_size=0
numput(datasize, riff_size, "UInt") ; little endian
file.rawwrite(riff_size, 4)

;///// DONE ///////


ExitApp
return


RecordFunction(handle, buffer, length, user)
{
	global file
	global datasize

	file.rawwrite(buffer+0,length)
	datasize += length
	
	return true
}

User avatar
Delta Pythagorean
Posts: 561
Joined: 13 Feb 2017, 13:44
GitHub: DelPyth
Location: Somewhere in the US

Re: Record a WAV file with BASS.dll

12 Jul 2017, 03:05

There's a little problem, the file is corrupt and Windows will not read it. I've tried it in a few programs and they all say it's corrupted. I might have a different version or download of bass.dll

- [AHK].......: 1.1.33.00 Unicode 64-bit
- [OS].........: Windows 10.0.18362
- [GITHUB]...: github.com/DeltaPyth
- [PAYPAL]....: paypal.me/DelPyth
- [DISCORD]..: Delta#3324

Remember to use [code]CODE[/code] for your multi-line scripts.
Stay safe, stay inside, and remember to wash your hands for 20 seconds!
User avatar
Masonjar13
Posts: 1514
Joined: 20 Jul 2014, 10:16
GitHub: Masonjar13
Location: Не Россия

Re: Record a WAV file with BASS.dll

12 Jul 2017, 03:35

I've never used bass.dll before, but this is quite cool! I wrote a class wrapper for it.

Code: Select all

#singleInstance force
#persistent
#include *i <Lib_1>
SetBatchLines, -1
i:=0

Gui, Add, Button, x182 y99 w100 h30 gStartRecord, Start
Gui, Add, Button, x182 y149 w100 h30 gStopRecord disabled, Stop
; Generated using SmartGUI Creator for SciTE
Gui, Show, w479 h379, bassRecord Test
recording:=new bassRecord(a_scriptDir . "\bass64.dll")
return

GuiClose:
ExitApp


StartRecord:
recording.start("test_" . i++ ".wav")
control,disable,,Start
control,enable,,Stop
return

StopRecord:
recording.stop()
control,enable,,Start
control,disable,,Stop
return

class bassRecord {
    
    __new(bassLoc:=""){
        this.bassLoc:=bassLoc?bassLoc:a_scriptDir . "\bass.dll"
        return this
    }
    
    __delete(){
        if(this.currentFile)
            this.stop()
    }
    
    start(fileName){
        if(this.currentFile)
            return 1
        
        this.currentFile:=fileName

        this.recordCallback:=registerCallback("_callback","","",&this)
        dllCall(this.recordCallback,"int",42)
        this._writeWAV(fileName)
        
        if(!this.bToken)
            this.bToken:=DllCall("LoadLibrary","str",this.bassLoc) 
        DllCall(this.bassLoc . "\BASS_RecordInit", Int,-1)
        DllCall(this.bassLoc . "\BASS_ErrorGetCode")
        this.hrecord := DllCall(this.bassLoc . "\BASS_RecordStart", UInt, 44100, UInt, 2, UInt, 0, UInt, this.recordCallback, UInt, 0)
    }
    
    stop(){
        DllCall(this.bassLoc . "\BASS_ChannelStop", UInt,this.hrecord)
        this.file.seek(40)
    
        data_datasize=0
        numput(this.datasize, data_datasize, "UInt") ; little endian
        this.file.rawwrite(data_datasize, 4)

        this.datasize+=36

        this.file.seek(4)

        riff_size=0
        numput(this.datasize, riff_size, "UInt") ; little endian
        this.file.rawwrite(riff_size, 4)
        dllCall("GlobalFree","ptr",this.recordCallback)
        this.file.close()
        this.currentFile:=""
    }
    
    _writeWAV(fileName){
        this.file := fileopen(fileName, "rw", CP1252)
        this.file.write("RIFF    ") ; leave space for file size - 8

        this.file.write("WAVEfmt ") ; Wave Container, 'fmt ' chunk, this takes up 8 bytes.

        this.file.writeUInt(16) ; 16 bytes, length of formatchunk in bytes

        this.file.writeUShort(1) ; format, 1 = PCM, linear aka non compressed

        this.file.writeUShort(2) ; 2 channels

        this.file.writeUInt(44100) ; 44100 samples per second

        this.file.writeUInt(146400) ; bytes per second, 176400

        this.file.writeUShort(4) ; NumChannels * BitsPerSample/8

        this.file.writeUShort(16) ; 16 bit resolution

        this.file.write("data    ") ; this takes up 8 bytes. leave space to write in the size of data chunk.
        this.datasize := 0
    }
    
    callback(handle,buffer,length,user){
        this.file.rawwrite(buffer+0,length)
        this.datasize += length
        return true
    }
}

_callback(handle,buffer,length,user){
    return Object(a_eventInfo).callback(handle,buffer,length,user)
}
@Delta Pythagorean, try their official site (download links are at the very top of the page). Remember, if you're using 64-bit AHK, you'll need to use the 64-bit DLL, likewise to 32-bit versions.

Edit: changed code based on just me's suggestion.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
BoBo
Posts: 2981
Joined: 13 May 2014, 17:15

Re: Record a WAV file with BASS.dll

12 Jul 2017, 03:36

Delta Pythagorean wrote:There's a little problem, the file is corrupt and Windows will not read it. I've tried it in a few programs and they all say it's corrupted. I might have a different version or download of bass.dll
You've probably used the 32- <?> 64-bit version? [More..]

Code: Select all

BASS 2.4
Copyright (c) 1999-2016 Un4seen Developments Ltd. All rights reserved.

Files that you should have found in the BASS package
====================================================
Win32 version
-------------
BASS.TXT        This file
BASS.DLL        BASS module
BASS.CHM        BASS documentation
MP3-FREE\
  BASS.DLL        BASS module using the OS's MP3 decoder
X64\
  BASS.DLL        64-bit BASS module
  MP3-FREE
    BASS.DLL        64-bit BASS module using the OS's MP3 decoder 
 .
 .
 .   
just me
Posts: 7097
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Record a WAV file with BASS.dll

12 Jul 2017, 04:02

Code like

Code: Select all

fmt_length = 0
numput(16, fmt_length, "UInt") ; 16 bytes, length of formatchunk in bytes
file.rawwrite(fmt_length, 4)
might be replaced by

Code: Select all

fmt_length := 16 ; 16 bytes, length of formatchunk in bytes
file.WriteUInt(fmt_length)
User avatar
Masonjar13
Posts: 1514
Joined: 20 Jul 2014, 10:16
GitHub: Masonjar13
Location: Не Россия

Re: Record a WAV file with BASS.dll

12 Jul 2017, 07:10

Updated to allow different sample and bit rates, as well as channels. Bass.dll only supports 8, 16, and 32-bit rates. If it's not one of those though, it'll default to 16, for safety. Being a WAV, it should support up to 2^16-1 channels and 2^32-1 sample rate, but I'm not sure of the limitations of Bass.dll.

Code: Select all

#singleInstance force
#persistent
#include *i <Lib_1>
setBatchLines, -1
i:=0

gui,add,button,x182 y99 w100 h30 gStartRecord,Start
gui,add,button,x182 y149 w100 h30 gStopRecord disabled,Stop
recording:=new bassRecord(a_scriptDir . "\bass64.dll")
recording.sampleRate:=48000
recording.bitRate:=16
recording.channelCount:=1
gui,show,w479 h379,bassRecord Test
return

guiClose:
exitApp


StartRecord:
recording.start("test_" . i++ ".wav")
control,disable,,Start
control,enable,,Stop
return

StopRecord:
recording.stop()
control,enable,,Start
control,disable,,Stop
return

class bassRecord {
    channelCount:=2
    sampleRate:=44100
    bitRate:=16
    
    __new(bassLoc:=""){
        this.bassLoc:=bassLoc?bassLoc:a_scriptDir . "\bass.dll"
        return this
    }
    
    __delete(){
        if(this.currentFile)
            this.stop()
    }
    
    start(fileName){
        if(this.currentFile)
            return 1
        
        this.currentFile:=fileName

        this.recordCallback:=registerCallback("_callback","","",&this)
        dllCall(this.recordCallback,"int",42)
        this._writeWAV(fileName)
        
        if(!this.bToken)
            this.bToken:=dllCall("LoadLibrary","str",this.bassLoc) 
        dllCall(this.bassLoc . "\BASS_RecordInit","Int",-1)
        ;dllCall(this.bassLoc . "\BASS_ErrorGetCode")
        this.hrecord:=dllCall(this.bassLoc . "\BASS_RecordStart","UInt",this.sampleRate,"UInt",this.channelCount,"UInt",bitRate=8?1:bitRate=32?256:0,"UInt",this.recordCallback,"UInt", 0)
    }
    
    stop(){
        dllCall(this.bassLoc . "\BASS_ChannelStop","UInt",this.hrecord)
        dllCall("GlobalFree","Ptr",this.recordCallback)
        this.file.seek(40)
    
        this.file.writeUInt(this.datasize) ;little endian

        this.datasize+=36

        this.file.seek(4)

        this.file.writeUInt(this.datasize)
        
        this.file.close()
        this.currentFile:=""
    }
    
    _writeWAV(fileName){
        this.file := fileopen(fileName, "rw", CP1252)
        this.file.write("RIFF    ") ; leave space for file size - 8

        this.file.write("WAVEfmt ") ; Wave Container, 'fmt ' chunk, this takes up 8 bytes.

        this.file.writeUInt(16) ; 16 bytes, length of formatchunk in bytes

        this.file.writeUShort(1) ; format, 1 = PCM, linear aka non compressed

        this.file.writeUShort(this.channelCount) ; 2 channels

        this.file.writeUInt(this.sampleRate) ; 44100 samples per second

        this.file.writeUInt(this.sampleRate*this.channelCount*this.bitRate/8) ; bytes per second, 176400

        this.file.writeUShort(this.channelCount*this.bitRate/8) ; NumChannels * BitsPerSample/8

        this.file.writeUShort(this.bitRate) ; 16 bit bitRate

        this.file.write("data    ") ; this takes up 8 bytes. leave space to write in the size of data chunk.
        this.datasize := 0
    }
    
    callback(handle,buffer,length,user){
        this.file.rawwrite(buffer+0,length)
        this.datasize += length
        return true
    }
}

_callback(handle,buffer,length,user){
    return Object(a_eventInfo).callback(handle,buffer,length,user)
}
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
metacognition
Posts: 87
Joined: 22 Oct 2014, 05:57
Location: Alaska

Re: Record a WAV file with BASS.dll

12 Jul 2017, 14:58

@Masonjar13 Cool! Thanks!
@justme Thanks, I didn't know about that .WriteNum method! Simplifies things...
DanielToward13
Posts: 71
Joined: 18 May 2017, 10:56

Re: Record a WAV file with BASS.dll

29 Jul 2017, 10:01

Could you share the bass64.dll and the BASS LIB? I have tried three versions on the internet but they doesn't work. I could not find the 64bit DLL from https://www.un4seen.com
User avatar
metacognition
Posts: 87
Joined: 22 Oct 2014, 05:57
Location: Alaska

Re: Record a WAV file with BASS.dll

29 Jul 2017, 10:17

http://www.un4seen.com/download.php?bass24

the 64 bit dll would be in the "x64" folder.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: dcrossmier and 43 guests