bassaudio

1.1.1 • Public • Published

Un4Seen Bass Audio Library Wrapper

Bass Audio library is the best audio library to play, edit, convert, stream etc. this wrapper wraps most of the "audio playback" features using ffi , ref , ref-struct .

ffi enables to call c library methods, properties , callbacks etc.

Compatible with?

tested on MacosX El capitan, windows 32 and 64 bits, ubuntu 14+, raspberrypi 2-3 (armv7), not tested on armv6 but its easy to test, just install and see.. related platform binaries can be downloaded from bass web page..

Warning

Please put the required bass audio library files to root folder (dll files for windows, so files for *nix, dylib files for macos)

Download the required dll files from http://www.un4seen.com. i did not include the required files in this module..

Read full documentation of bass from its original help. i Will only write same simple examples.

Features:

  • BASS_Init

  • BASS_GetVersion

  • BASS_StreamCreateFile

  • BASS_StreamCreateURL

  • BASS_StreamFree

  • BASS_ChannelPlay

  • BASS_ChannelStop

  • BASS_ChannelPause

  • BASS_ChannelGetPosition

  • BASS_ChannelSetPosition

  • BASS_ChannelGetLength

  • BASS_ChannelBytes2Seconds

  • BASS_ChannelSeconds2Bytes

  • BASS_ChannelGetLevel

  • BASS_ChannelRemoveSync

  • BASS_ChannelIsActive

  • BASS_ChannelSetAttribute

  • BASS_ChannelGetAttribute

  • BASS_ChannelSetSync

  • BASS_ChannelSlideAttribute

  • BASS_ChannelIsSliding

  • BASS_ChannelGetDevice

  • BASS_ChannelSetDevice

  • BASS_StreamFree

  • BASS_SetDevice

  • BASS_SetVolume

  • BASS_Start

  • BASS_Stop

  • BASS_Pause

  • BASS_GetInfo

  • BASS_ErrorGetCode

  • BASS_Free

  • BASS_GetCPU

  • BASS_GetDevice

  • BASS_GetDeviceInfo

  • BASS_ChannelGetTags

  • BASS_Mixer_StreamCreate

  • BASS_Mixer_StreamAddChannel

  • BASS_Mixer_ChannelGetLevel

  • BASS_Mixer_ChannelGetMixer

  • BASS_Mixer_ChannelGetPosition

  • BASS_Mixer_ChannelRemove

  • BASS_Mixer_ChannelRemoveSync

  • BASS_Mixer_ChannelSetPosition

  • BASS_Mixer_ChannelSetSync

  • BASS_Encode_Start

  • BASS_Encode_IsActive

  • BASS_Encode_SetNotify

  • BASS_Encode_SetPaused

  • BASS_Encode_Stop

  • BASS_Encode_CastInit

  • BASS_Encode_CastGetStats

  • BASS_Encode_CastSetTitle

  • BASS_Split_StreamCreate

  • BASS_Split_StreamGetAvailable

  • BASS_Split_StreamGetSource

  • BASS_Split_StreamGetSplits

  • BASS_Split_StreamReset

  • BASS_Split_StreamResetEx

Extra:

SYNCPROC also implemented

Installation

Install with npm : npm install bassaudio

Examples

basic load and play file

var bass=require('bassaudio');
var basslib=new bass();
 
 //get all sound cards
 var cards=basslib.getDevices();
 console.log('total found sound cards:' + cards.length)
 //lets print first sound card's info, find out more inside source code..
 //first item in array '[0]' is "no sound" , then use the item [1]
 //you will see that card isInitialized will be false, because we did not init it yet..
 var card=cards[1];
 console.log(card.name + ' is enabled:' + card.enabled + ' ,IsDefault:' + card.IsDefault + ' , IsInitialized:' + card.IsInitialized + ' ,typeSpeakers:' + card.typeSpeakers)
 
// [device],[freq],[flags] , -1 is default sound card
var result=basslib.BASS_Init(-1,44100,basslib.BASS_Initflags.BASS_DEVICE_STEREO)
if(!result){
  console.log('error init sound card:' + basslib.BASS_ErrorGetCode())
}
 
console.log("first card is init?:" + basslib.getDevice(1).IsInitialized)
 
// isMemoryFile,filename,offset,length,flags, returns pointer of file
var chan=basslib.BASS_StreamCreateFile(0,'c:\\mp3\\test.mp3',0,0,0)
if(basslib.BASS_ErrorGetCode()!=basslib.BASS_ErrorCode.BASS_OK){
  console.log('error opening file:' + basslib.BASS_ErrorGetCode())
}
 
//lets play
//channel,restart   , returns  (also there are stop , pause commands)
var success=basslib.BASS_ChannelPlay(chan,-1)
if(!success){
  console.log('error playing file:' + basslib.BASS_ErrorGetCode())
}

Get Duration

//get the duration, bass returns the total bytes of the channel pointer, then we must convert it to seconds :)
var durationInBytes= basslib.BASS_ChannelGetLength(chan,0)
var durationInSeconds=basslib.BASS_ChannelBytes2Seconds(chan,durationInBytes)

Get Duration Example2

//if stream is active (playing), then get position and duration..
setInterval(function(){
    if(basslib.BASS_ChannelIsActive(chan)==basslib.BASS_ChannelIsActiveAttribs.BASS_ACTIVE_PLAYING) {
 
        var position = basslib.BASS_ChannelBytes2Seconds(chan, basslib.BASS_ChannelGetPosition(chan, 0));
        var duration = basslib.BASS_ChannelBytes2Seconds(chan, basslib.BASS_ChannelGetLength(chan, 0))
        console.log(position + ' / ' + duration)
    }else{
        console.log('stopped' )
    }
},500)

Get Volume of channel

var ref=require('ref')
//set a float pointer
var volume=ref.alloc('float');
//get the volume
var result=basslib.BASS_ChannelGetAttribute(chan,basslib.BASS_ChannelAttributes.BASS_ATTRIB_VOL,volume);
//now deref volume to get the value
console.log(ref.deref(volume))
 

Set Volume

//lets set to 0.3
basslib.BASS_ChannelSetAttribute(chan,basslib.BASS_ChannelAttributes.BASS_ATTRIB_VOL,0.3)

Get current Position of playback

var positionInBytes= basslib.BASS_ChannelGetPosition(chan,0);
//now convert it to seconds
var position=basslib.BASS_ChannelBytes2Seconds(chan,positionInBytes);

Set Position

//first get the byte position of desired seconds (ex:to last 10 seconds
var Last10SecondsBytePos=basslib.BASS_ChannelSeconds2Bytes(chan,durationInSeconds-10);
basslib.BASS_ChannelSetPosition(chan,Last10SecondsBytePos);

Is channel is playing?

var result=basslib.BASS_ChannelIsActive(chan)
if(result==basslib.BASS_ChannelIsActiveAttribs.BASS_ACTIVE_PLAYING){
  console.log('channel is playing')
}
 

sliding

//Lets slide volume to 0 in 3 seconds (3000 milliseconds)
basslib.BASS_ChannelSlideAttribute(chan,basslib.BASS_ChannelAttributes.BASS_ATTRIB_VOL,0,3000)

callback

//lets make a callback when position reaches to 20. seconds.
var Pos20SecondsBytePos=basslib.BASS_ChannelSeconds2Bytes(chan,20);
var proc20SecondsID=basslib.BASS_ChannelSetSync(chan,basslib.BASS_ChannelSyncTypes.BASS_SYNC_POS,Pos20SecondsBytePos,function(handle,channel,data,user){
   if(handle==proc20SecondsID){
      console.log('position reached to the 20 seconds..')
   }
})
 
//lets get the event when the position reaches to end
var procTOENDID=basslib.BASS_ChannelSetSync(chan,basslib.BASS_ChannelSyncTypes.BASS_SYNC_END,0,function(handle,channel,data,user){
   if(handle==procTOENDID){
      console.log('playback finished..')
   }
})

vumeter

//lets get vumeter :)
 var levels=basslib.BASS_ChannelGetLevel(chan);
 //its a 64 bit value, lets get lo and hiwords
 var rightlevel=basslib.toFloat64(levels)[0]
var leftlevel=basslib.toFloat64(levels)[1]

close the file

if(basslib.BASS_ChannelIsActive(chan)==basslib.BASS_ChannelIsActiveAttribs.BASS_ACTIVE_PLAYING){
  //stop the channel
  basslib.BASS_ChannelStop(chan);
  }
 
  var result=basslib.BASS_StreamFree(chan)
  if(!result){
    console.log('stream free error:' + basslib.BASS_ErrorGetCode())
  }

change sound card

  //first check if this sound card is initialized
  var soundCardIndex=1;
  var info=basslib.getDevice(soundCardIndex);
  if(!info.enabled){
    console.log('this device is not enabled')
  }
  if(!info.IsInitialized){
        var result= basslib.BASS_Init(soundCardIndex,44100,basslib.BASS_Initflags.BASS_DEVICE_STEREO);
        if(result!=basslib.BASS_ErrorCode.BASS_OK){
          console.log('error init sound card:' + basslib.BASS_ErrorGetCode())
        }
  }
  var success=basslib.BASS_ChannelSetDevice(chan,soundCardIndex)
  if(!success){
      console.log('error init sound card:' + basslib.BASS_ErrorGetCode())
   }

Info of a channel

var info=    basslib.BASS_ChannelGetInfo(chan);
console.log('info.ctype:' + info.ctype)
    console.log("is channel an mp3 stream?:" + (info.ctype ==basslib.BASS_CHANNELINFOtypes.BASS_CTYPE_STREAM_MP3))
//other infos are: freq,chans,flags,ctype,origres,plugin,sample,filename

Info of a device

var info=    basslib.getInfo();
console.log('speaker count:' + info.speakers)
console.log('minimum buffer:' + info.minbuf)
console.log('latency:' + info.latency)

Free the memory from bass

   basslib.BASS_Free();

MIXER FEATURES

Enable Mixer

//before using mixer, first enable it. and put the required component to root folder.
basslib.EnableMixer(true);

Mixer is Enabled?

//before using mixer, first enable it. and put the required component to root folder.
console.log(basslib.MixerEnabled());

Create mixer stream

basslib.EnableMixer(true);
var mixer=basslib.BASS_Mixer_StreamCreate(44100, 2,basslib.BASSFlags.BASS_SAMPLE_FLOAT);
var chan1=basslib.BASS_StreamCreateFile(0,'d:\\mp3\\tes1.mp3',0,0,basslib.BASSFlags.BASS_STREAM_DECODE | basslib.BASSFlags.BASS_SAMPLE_FLOAT)
var chan2=basslib.BASS_StreamCreateFile(0,'d:\\mp3\\test2.mp3',0,0,basslib.BASSFlags.BASS_STREAM_DECODE | basslib.BASSFlags.BASS_SAMPLE_FLOAT)
var ok1 = basslib.BASS_Mixer_StreamAddChannel(mixer, chan1, basslib.BASSFlags.BASS_SAMPLE_DEFAULT);
var ok2 = basslib.BASS_Mixer_StreamAddChannel(mixer, chan2, basslib.BASSFlags.BASS_SAMPLE_DEFAULT);
basslib.BASS_ChannelPlay(mixer,0)

Get current Position of mixer playback

var positionInBytes= basslib.BASS_Mixer_ChannelGetPosition(chan,0);
//now convert it to seconds
var position=basslib.BASS_ChannelBytes2Seconds(chan,positionInBytes);

ENCODER FEATURES

you can directly encode and send output to shotcast and icecast servers

use mixer as a trick, because if the channel freed or added new channel, the encoder stops itself.

add channels to mixer every time, and add mixer channel to encoder. so the encoder never stops..

Init encoder

basslib.EnableMixer(true);
var mixer=basslib.BASS_Mixer_StreamCreate(44100, 2,basslib.BASSFlags.BASS_SAMPLE_FLOAT);
var chan=basslib.BASS_StreamCreateFile(0,'d:\\mp3\\tes1.mp3',0,0,basslib.BASSFlags.BASS_STREAM_DECODE | basslib.BASSFlags.BASS_SAMPLE_FLOAT)
var ok = basslib.BASS_Mixer_StreamAddChannel(mixer, chan, basslib.BASSFlags.BASS_SAMPLE_DEFAULT);
 
basslib.EnableEncoder(true);
 
//lets try icecast
var enc_chan=basslib.BASS_Encode_Start(mixer,'lame -r -m s -s 22050 -b 56 -',basslib.BASS_Encode_Startflags.BASS_ENCODE_NOHEAD);
var result=basslib.BASS_Encode_CastInit(enc_chan,
                                     'http://server-ip:8000/test',
                                     'password',
                                     basslib.BASS_Encode_CastInitcontentMIMEtypes.BASS_ENCODE_TYPE_MP3,
                                     'test stream',
                                     'http://your-server-ip',
                                     'pop',
                                     'this is my new icecast test',
                                     'header1\r\nheader2\r\n',
                                     44100,
                                     true //public
                                     );
 
basslib.BASS_ChannelPlay(mixer,0);                                     

get notification from encoder server

var result=basslib.BASS_Encode_SetNotify(enc_chan,function(handle,status,user){
  if(status==basslib.EncoderNotifyStatus.BASS_ENCODE_NOTIFY_CAST){
  console.log('server connection is dead');
});

mono speaker output

//lets say if you have 5.1 speaker and want to use each output stereo or mono
//basically with 5.1 output you can use 6 different output channels.
//this example shows how to do it
 var bass=require('bassaudio')
 var basslib=new bass();
 
 
 //set init to speakers
 var result=basslib.BASS_Init(-1,44100,basslib.BASS_Initflags.BASS_DEVICE_SPEAKERS)
 if(!result){
     console.log('error init sound card:' + basslib.BASS_ErrorGetCode())
 }
 
 //to use mixer feature, you have to enable it
 basslib.EnableMixer(true);
 
  var cards=basslib.getDevices();
  var speakerCount=basslib.getInfo().speakers;
  console.log('we have',speakerCount,'speakers')
  var path=require('path')
  var f1=path.join(__dirname, '1.mp3')
 
 
 //create a mixer and tell it to output front right
 var mixer=basslib.BASS_Mixer_StreamCreate(44100, 1,basslib.BASS_SPEAKERtypes.BASS_SPEAKER_FRONTRIGHT);
 console.log('mixer:',mixer,' error code:',basslib.BASS_ErrorGetCode())
 
 //set channel to decode
 var chan1=basslib.BASS_StreamCreateFile(0,f1,0,0,basslib.BASSFlags.BASS_STREAM_DECODE )
 
 //if your file is stereo , you have to downmix to mono, else you cannot get it mono output to only 1 speaker.
 var ok1 = basslib.BASS_Mixer_StreamAddChannel(mixer, chan1, basslib.BASS_MIXERsourceflags.BASS_MIXER_DOWNMIX);
 var ok2=basslib.BASS_ChannelPlay(mixer,0)
 
 
 console.log('chan1:',chan1,' error code:',basslib.BASS_ErrorGetCode())
 console.log('ok1:',ok1,' error code:',basslib.BASS_ErrorGetCode())
 
  setInterval(()=>{},1000)

splitting channels

//if you want to add a mixer to another mixer, it is not possible/supported
//but there is another way to do it.
//you can split any channel or mixer into two, then you can use the new splitted channel on any other mixer.
//A "splitter" basically does the opposite of a mixer: it splits a single source into multiple streams rather then mixing multiple sources into a single stream. Like mixer sources, splitter sources must be decoding channels.
 
var splitChan=basslib.BASS_Split_StreamCreate(mixer,0)
var splits=basslib.BASS_Split_StreamGetSplits(mixer)
var splitsource=basslib.BASS_Split_StreamGetSource(splitChan)
var avail1=basslib.BASS_Split_StreamGetAvailable(splitChan)
var avail2=basslib.BASS_Split_StreamGetAvailable(mixer)

INFO i only added methods, properties what i needed.. add yours to the code or send me mail..

IMPORTANT

Below modifications are now handled internally. You shouldn't need to do these manually. However, if you do, you know where to find them.

2017-02-10

please modify node_modules/ffi/lib/callback.js if you are using callbacks. ffi garbage collector removes callbacks after 10 seconds. with this modification, callbacks stays on memory

at line 81 , before return, add;

Object.defineProperty(func, '_func', {value:callback});

--------------------------------

2017-01-31

please modify node_modules/ffi/lib/library.js if you are using linux os and if you are using addons. ffi loads bass into instance, not as global instance.. so the addons could not find main bass on memory. this fixes that issue.. (on windows and macos, it works without this modification)

find

 var dl = new DynamicLibrary(libfile || null, RTLD_NOW)

change it to

var dl = new DynamicLibrary(libfile || null, RTLD_NOW | DynamicLibrary.FLAGS.RTLD_GLOBAL)

UPDATE LOG

--------------------------------

  • 1.1.1

    bugfix..

  • 1.1.0

    updates:

    its been too much time passed since i created this library. i was using it when node was 8.x.x , so some libraries are outdated. updated to the latest ffi and ref libraries with newer napi implementation. as you know, ffi and ref are the gateway between c, c++ libraries and nodejs.. so what changed? just 3 libs and 3 lines.. yep.. now it supports newer nodejs versions..

    var Struct = require('ref-struct-napi');
    var ref = require('ref-napi');
    var ffi = require('ffi-napi');

    thanks to RiccardoBiemmi the creator of bassaudiolibrary while i was not here, he updated the code.. but he just added his needs.. anyway, use his, or my work.. its up to you.. and add new features..

  • 1.0.8

    new features added:

    • BASS_Split_StreamCreate

    • BASS_Split_StreamGetAvailable

    • BASS_Split_StreamGetSource

    • BASS_Split_StreamGetSplits

    • BASS_Split_StreamReset

    • BASS_Split_StreamResetEx

  • 1.0.7

    • BASS_SetConfigflags, BASS_SetConfig, BASS_GetConfig, BASS_Update, BASS_ChannelUpdate features added
  • 1.0.6

    • correct an arg type in BASS_Encode_CastInit handler
  • 1.0.5

    • lock installed "ffi" version
    • add shim to automate the changes to the "ffi" source code
  • 1.0.4

    • BASS_Encode_CastSetTitle has a minor bug. fixed.
  • 1.0.3

    • constructor now accepts and options object
    • examples folder comes with link files
  • 1.0.2

    • getVolume() gives ref error when channel is 0. fixed.
  • 1.0.1

    • some types fixed for raspberrypi compability.
    • examples folder added
    • mono speaker out example added
  • 1.0.0 Release

    • i hope i fixed everything :) lets cross the fingers..
  • 1.0.0-rc.22

    • some types in BASS_StreamCreateFile are changed to ref.types.int64
  • 1.0.0-rc.21

    • these fixes are for linux environment
    • fixed BASS_ChannelBytes2Seconds
    • fixed BASS_ChannelSeconds2Bytes
    • fixed BASS_ChannelSetPosition
  • 1.0.0-rc.20

    • added BASS_MIXERsourceflags
    • found a bug on ffi source code, see above change for linux os..
  • 1.0.0-rc.18

    • BASS_ChannelGetAttribute returns float pointer. fixed.see getvolume example for usage.
    • BASS_GETInfo now works.
  • 1.0.0-rc.17

    • BASS_Encode_IsActive fixed
  • 1.0.0-rc.16

    • getDevice(-1) must find the default sound card and return it.
    • BASS_GetDevice takes 1 argument, but missing in code. fixed.
  • 1.0.0-rc.15

    • documentation fix
  • 1.0.0-rc.14

    • documentation fix
  • 1.0.0-rc.13

    • new mixer features:

      • BASS_Mixer_StreamCreate
      • BASS_Mixer_StreamAddChannel
      • BASS_Mixer_ChannelGetLevel
      • BASS_Mixer_ChannelGetMixer
      • BASS_Mixer_ChannelGetPosition
      • BASS_Mixer_ChannelRemove
      • BASS_Mixer_ChannelRemoveSync
      • BASS_Mixer_ChannelSetPosition
      • BASS_Mixer_ChannelSetSync
    • new encoder features:

      • BASS_Encode_Start
      • BASS_Encode_IsActive
      • BASS_Encode_SetNotify
      • BASS_Encode_SetPaused
      • BASS_Encode_Stop
      • BASS_Encode_CastInit
      • BASS_Encode_CastGetStats
      • BASS_Encode_CastSetTitle
  • 1.0.0-rc.12

    • BASS_ChannelBytes2Seconds and BASS_ChannelSeconds2Bytes returns wrong on arm cpu. pos value type changed to int64. now works correctly

Package Sidebar

Install

npm i bassaudio

Weekly Downloads

2

Version

1.1.1

License

MIT

Unpacked Size

1.79 MB

Total Files

22

Last publish

Collaborators

  • doruk
  • serkanp
  • cankuscu