BASS for iOS (iPhone/iPad)

Started by Ian @ un4seen,

darren

Hello Ian,
Problem: Apply DSP effects and Tempo changes to a single stream, and modifying parameters over time

What I've tried: I thought I needed to use a mixer to accomplish this. I can add the DSP channel to a mixer stream (without errors), but to hear any output my callback needs to call the original stream, not the mixer.

Conceptually I think I am trying to build this:

create mixer -> create a DSP channel -> add to mixer -> start playing -> modify channel params in realtime


Here's some code snippets:

// 1.  create a mixer
self.mixStream = BASS_Mixer_StreamCreate(kSampleRate, channelCount, flags);

// 2. create some channels, 1 for the DSP effects, 1 for tempo changes
self.fxstream=BASS_StreamCreate( kSampleRate, channelCount, flags, STREAMPROC_PUSH, NULL);

// the DSP effect to be applied
BASS_DX8_ECHO echo; echo.fFeedback = 0.0; echo.fWetDryMix = 0.0; echo.lPanDelay = 1.0; echo.fLeftDelay = 100.0; echo.fRightDelay = 100.0;

// apply the effect
self.echoFX = BASS_ChannelSetFX(self.fxstream, BASS_FX_DX8_ECHO, 2); // set FX on it , 3rd param is the priority
BASS_FXSetParameters(self.echoFX, &echo);

// add the effect stream to the mixer
BOOL okEcho= BASS_Mixer_StreamAddChannel(mixStream, self.echoFX, BASS_MIXER_BUFFER | BASS_MIXER_NORAMPIN);


====== FX ====== // toggle on and off
BASS_DX8_ECHO echo; echo.fFeedback = 50.0; echo.fWetDryMix = 50.0; echo.lPanDelay = 1.0; echo.fLeftDelay = 100.0; echo.fRightDelay = 100.0;
BASS_FXSetParameters(self.echoFX, &echo);


===== Callback ===== // actually plays the music

// THIS version works by playing the stream BEFORE it's added to the mixer
BASS_StreamPutData(auGraphController.fxstream, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize);
BASS_ChannelGetData(auGraphController.fxstream, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize);

// THIS also plays, but without allowing me to hear any changes to FX
BASS_StreamPutData(auGraphController.mixStream, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize);   
DWORD queueDataSize = BASS_StreamPutData(auGraphController.mixStream, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize);
BASS_ChannelGetData(BASS_FX_TempoGetSource(auGraphController.mixStream), ioData->mBuffers[0].mData, queueDataSize);


Any thoughts?
The whole point of this is to be able to add a tempo-changing stream later in the chain that I can also modify in realtime.
Will this be possible?

Darren


Ian @ un4seen

Quote from: darren// add the effect stream to the mixer
BOOL okEcho= BASS_Mixer_StreamAddChannel(mixStream, self.echoFX, BASS_MIXER_BUFFER | BASS_MIXER_NORAMPIN);

It looks like that should be "self.fxstream" instead of "self.echoFX" there, but from what you say, it sounds like you probably don't really need a mixer. Or are you planning to play multiple sounds and apply the effects equally to all of them?

Quote from: darrenThe whole point of this is to be able to add a tempo-changing stream later in the chain that I can also modify in realtime.
Will this be possible?

I don't think it will be possible with your current output setup (eg. using an AudioUnit) as tempo processing changes the amount of data (eg. shrinks/expands it), meaning it can't be applied "in place" like an echo effect can. You would probably need to let BASS handle the playback. For example, something like this...

decoder=BASS_StreamCreateFile(FALSE, filename, 0, 0, BASS_STREAM_DECODE); // create a "decoding channel" from the music file
tempostream=BASS_FX_TempoCreate(decoder, BASS_FX_FREESOURCE); // create a tempo stream from it
BASS_ChannelSetFX(tempostream, ...); // set some FX
BASS_ChannelPlay(tempostream, FALSE); // start playing

Jonathan

pthread_mutexattr_destroy$UNIX2003 error is also present with BASS_Mixer.

Full message:
pthread_mutexattr_destroy$UNIX2003 called from function BASS_Mixer_GetVersion

Any chance you can port whatever fix you had to do for libbass.a to solve this issue in libbassmix.a as well?

Thanks, and great job on this library!  I love it!

Jonathan

Quote from: Jonathanpthread_mutexattr_destroy$UNIX2003 error is also present with BASS_Mixer.

Full message:
pthread_mutexattr_destroy$UNIX2003 called from function BASS_Mixer_GetVersion

Any chance you can port whatever fix you had to do for libbass.a to solve this issue in libbassmix.a as well?

Thanks, and great job on this library!  I love it!

Nevermind.. looks like I didn't clean my build before building with the new files provided from 1/13.  My mistake!

Thanks again!

Jonathan

Is there a way to do real-time (or near real-time) microphone monitoring through a mixer?  I have a BASS_MixerStream setup with two channels connected, one of which is an HRECORD stream pulling from the iPhone mic.  There's a significant delay from when I speak into the microphone and when I hear it in the headphones.

Using pure core-audio I am able to get near real-time monitoring by connecting the microphone and audio through the mixer unit, so I know it's possible.

Is there some setting I need to modify in order to get the microphone to work in this way with BASS?  I've tried playing with the various buffer settings and I just can't seem to get the mic playback to be real-time.

Any ideas?

Also, in terms of the sample rate, etc.. is 44100 / 2 Channel the best setting for iOS audio?  I think internally it uses floats so would it be better to use the FLOAT flag so there isn't any resampling?  Basically I want the lowest latency possible.

Thanks!

Ian @ un4seen

Quote from: JonathanIs there a way to do real-time (or near real-time) microphone monitoring through a mixer?  I have a BASS_MixerStream setup with two channels connected, one of which is an HRECORD stream pulling from the iPhone mic.  There's a significant delay from when I speak into the microphone and when I hear it in the headphones.

That delay will primarily be due to the mixer's playback buffer. The length of that can be reduced via the BASS_CONFIG_BUFFER option, but you could also try enabling the BASS_ATTRIB_NOBUFFER attribute on the mixer to bypass the buffering...

BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_NOBUFFER, 1);
Please see the BASS_ATTRIB_NOBUFFER documentation for details.

When a recording channel is plugged into a mixer, it is also usually a good idea to enable the BASS_MIXER_LIMIT flag on it (in its BASS_Mixer_StreamAddChannel call), so that the mixer will only process as much data as is available from the recording.

Quote from: JonathanAlso, in terms of the sample rate, etc.. is 44100 / 2 Channel the best setting for iOS audio?  I think internally it uses floats so would it be better to use the FLOAT flag so there isn't any resampling?  Basically I want the lowest latency possible.

Floating-point or integer shouldn't matter too much, but it is best for quality and efficiency to use the device's native sample rate when creating the mixer and recording channel. That information is available from BASS_GetInfo, in the "freq" value (see "speakers" too for the mixer "chans" parameter).

Jonathan

QuoteThat delay will primarily be due to the mixer's playback buffer. The length of that can be reduced via the BASS_CONFIG_BUFFER option, but you could also try enabling the BASS_ATTRIB_NOBUFFER attribute on the mixer to bypass the buffering...

I had tried most of what you wrote in your last post.  The problem I was seeing was that I was setting the preferred IO buffer duration to .005, then retrieving it to make sure I was getting it set correctly.  After that, I initialize BASS as well as the recording, and then the buffer went to .023.   .023 is no good for realtime recording and playback.  The strange thing is afterwards I would try resetting the IO buffer duration but it wouldn't budge.

Does BASS do something with the audio session?  Maybe listen for changes or something and then re-enable its setting.  Does it touch the IO buffer duration?

Here's a snippet:


Float32 fpref_duration = 0.005;
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(fpref_duration), &fpref_duration);

// Here it's set to .005 correctly

// Init BASS
BASS_Init(-1, 44100, 0, NULL, NULL);
BASS_RecordInit(-1);

// Here it's now set to .023, I'm assuming by BASS

// Re-set to .005
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(fpref_duration), &fpref_duration);

// Here it's actually still .023

Any ideas?  Does BASS explicitly set the buffer for the session with respect to the config variables?




Jonathan

Quotebut you could also try enabling the BASS_ATTRIB_NOBUFFER attribute on the mixer to bypass the buffering...

BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_NOBUFFER, 1);
Please see the BASS_ATTRIB_NOBUFFER documentation for details.

I don't see this anywhere.  Is this something that's unreleased?

Jonathan

First off, I apologize for the multiple posts.  I really should have gathered this all into one! :)

I've narrowed it down to the BASS_RecordInit(-1) function as far as the hardware IO buffer duration goes.  Something inside of that function is setting the duration back to 23ms (default for the session) and somehow making it so I can't change it back afterwards.  Is it getting explicitly set (or is the session getting reset)?

Ian @ un4seen

Quote from: JonathanAny ideas?  Does BASS explicitly set the buffer for the session with respect to the config variables?

BASS doesn't currently set the hardware buffer size, but it does set the audio category in BASS_Init/RecordInit, so perhaps it's getting reset in that? I'm not sure.

I've put an update for you to try in the iOS package (see 1st post), which extends the BASS_CONFIG_DEV_BUFFER option to the iOS version, to have BASS set a preferred hardware buffer size. If that's set to 0 (the default), the hardware buffer size will be left untouched by BASS. So, for example, your code above could be modified like this...

BASS_SetConfig(BASS_CONFIG_DEV_BUFFER, 5); // set 5ms device buffer
BASS_Init(-1, 44100, 0, NULL, NULL);
BASS_RecordInit(-1);

Let me know if changes are still not taking effect that way.

Quote from: Jonathan
Quotebut you could also try enabling the BASS_ATTRIB_NOBUFFER attribute on the mixer to bypass the buffering...

BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_NOBUFFER, 1);
Please see the BASS_ATTRIB_NOBUFFER documentation for details.

I don't see this anywhere.  Is this something that's unreleased?

That option was added in BASS 2.4.7, so it sounds like you may currently have an old BASS.H version. You can get the latest BASS.H file (and BASS.CHM) from the Win32 or OSX packages on the BASS webpage.

Jonathan

QuoteLet me know if changes are still not taking effect that way.

So using that config setting I get the following behavior:

- Before calling BASS functions, io duration = 0.023220 (default, ok)
- After calling BASS_Init with CONFIG_DEV_BUFFER before it = 0.005805 (adjusted, ok)
- After call to BASS_RecordInit = 0.023220 (back to default? Hmm?)

So it's definitely something inside of the RecordInit function.  I'm assuming you set the category to PlayAndRecord.. are you doing anything with the prefferedIObuffer property in there at all?  It is possible to set the buffer this way using PlayAndRecord as my older implementation (using remoteio for recording instead of BASS) works fine and retains the buffer correctly.  What manipulations to the audio session happen inside of RecordInit?

By the way, thanks for your help on all of this.  I really appreciate it!

Jonathan

Doing some more tinkering I've discovered that my version using audio units vs. BASS does in fact end up with a latency of 0.0232.  Perhaps this is a limitation of the device itself  when placed in PlaybackAndRecord.

So now, I'm back to some combination of the BASS settings being incorrect.  Since I use BASS successfully in my older version (just not for recording) I'm assuming it's something I've got set wrong either in the recording or in the mixer (I don't use a mixer in my older implementation).

- BASS_CONFIG_DEV_BUFFER = 5 (this is apparently invalid after playandrecord is set, so no point in setting this, actually)
- BASS_CONFIG_MIXER_BUFFER = 1.0f
- BASS_CONFIG_BUFFER = 24 + 1 (minimum buffer = 24... BASS_DEVICE_LATENCY will return 5, but we know that is incorrect once recording is initialized)
- Create mixer sstream with BASS_MIXER_NONSTOP
- SetAttribute for mixer: BASS_ATTRIB_NOBUFFER = 1
- Add record stream with BASS_MIXER_LIMIT

With that setup, I'm still seeing a delay on the playback that I don't see when I'm using pure coreaudio callbacks.  Am I missing a buffer?


Ian @ un4seen

I don't seem to be seeing the 23ms resetting here; it's still 5ms after the BASS_RecordInit call (which does indeed set the category to PlayAndRecord). Perhaps it depends on the OS version; what version are you using (I'm using 4.2.1), and do you see the same thing on both the device and simulator?

Regarding further reducing latency, the period set in the BASS_RecordStart call determines what size data blocks BASS will ask the OS to deliver. It defaults to 100ms, so you will probably want to reduce that. For example, you could do this for 10ms...

BASS_RecordStart(freq, chans, MAKELONG(0, 10), NULL, NULL); // start recording with 10ms period

Note when the BASS_ATTRIB_NOBUFFER option is enabled, the BASS_CONFIG_BUFFER setting won't have any effect on latency (the buffer is bypassed), so you don't really need to lower that (although it will save some memory). BASS_CONFIG_MIXER_BUFFER has no effect on latency either (it's related to the BASS_Mixer_ChannelGetData/Level functions).

Jonathan

I'm using an iPad on 3.2.  I'm not entirely sure why the buffer duration gets reset, but I'm assuming it is something with the version of iOS as you said.

I've got another issue using BASSenc.  I create a stream (BASS_STREAM_DECODE, STREAMPROC_PUSH) that I push to in the render of the audio output.  I then have another thread that loops and calls BASS_ChannelGetData() that triggers an encoder created using Encode_StartCAFile(AAC_ADTST, MPEG4AAC).  All of the sample rates match up but the audio in the output file sounds very slow and drawn out.  The pitch appears correct, but it sounds like the data is time stretched.

Any ideas what may be causing that?

Jonathan

I was getting extra data in because I forgot to filter by bus and only write on PostRender events in my callback.  My fault!

I will play with the buffer duration reset issue I'm seeing still, but I'm sure it's not BASS related as I completely removed the BASS calls and I still see it.  I have a feeling it's in issue with the first release of the iPad software (or maybe the iPad record hard is different than what's in the iPhone).

I'll let you know what I find out.

Ian @ un4seen

An updated iOS package is up (see the 1st post). For convenience, the device and simulator builds have been merged into one, so that no fiddling around with library versions is required.

Jamie Stevens

Hello,

Is it possible to load with BASS an mp3 file from the iPhone's iTunes library? Without this feature there are not so many things to do with BASS on this platform.

I saw other apps in the iTunes doing it, like ringtone designers, DJ apps etc. I don't think they were using BASS though?!

ppeau

Hey guys, with the new version of XCode 4 GM seed 2.
I've got this warning with BASS_FX :

Ld "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos/TurnTable Simulation.app/TurnTable Simulation" normal armv7
    cd "/Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation"
    setenv IPHONEOS_DEPLOYMENT_TARGET 4.3
    setenv PATH "/Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/usr/bin:/Users/ppeau/Xcode4/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2 -arch armv7 -isysroot /Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -L/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos "-L/Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation" -F/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos -filelist "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Intermediates/TurnTable Simulation.build/Debug-iphoneos/TurnTable Simulation.build/Objects-normal/armv7/TurnTable Simulation.LinkFileList" -dead_strip -miphoneos-version-min=4.3 -framework AudioToolbox -framework AVFoundation -framework CFNetwork -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -lbass_fx -lbass -o "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos/TurnTable Simulation.app/TurnTable Simulation"

ld: warning: ignoring file /Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation/libbass_fx.a, file was built for archive which is not the architecture being linked (armv7)

That works like a charm with XCode 3.2 but not with the new release of Xcode 4

Any idea ?

mits

#143
Hi,
I'm having the same issue using Xcode 4 (final release).
Do I need new libs of BASS_FX?

Thanks in advance.

Quote from: ppeauLd "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos/TurnTable Simulation.app/TurnTable Simulation" normal armv7
    cd "/Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation"
    setenv IPHONEOS_DEPLOYMENT_TARGET 4.3
    setenv PATH "/Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/usr/bin:/Users/ppeau/Xcode4/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2 -arch armv7 -isysroot /Users/ppeau/Xcode4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -L/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos "-L/Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation" -F/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos -filelist "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Intermediates/TurnTable Simulation.build/Debug-iphoneos/TurnTable Simulation.build/Objects-normal/armv7/TurnTable Simulation.LinkFileList" -dead_strip -miphoneos-version-min=4.3 -framework AudioToolbox -framework AVFoundation -framework CFNetwork -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -lbass_fx -lbass -o "/Users/ppeau/Library/Developer/Xcode/DerivedData/TurnTable_Simulation-afkttdegvfkwuaehbajwipzwknjd/Build/Products/Debug-iphoneos/TurnTable Simulation.app/TurnTable Simulation"

ld: warning: ignoring file /Users/ppeau/Dropbox/TurnTable Simulation/TurnTable Simulation/libbass_fx.a, file was built for archive which is not the architecture being linked (armv7)

ld: warning: ignoring file /Users/Mitsuhiro/Documents/iPhone APP/robick/libbass_fx.a, file was built for archive which is not the architecture being linked (armv7)
Undefined symbols for architecture armv7:
  "_BASS_FX_TempoGetSource", referenced from:
      -[AudioControllerBASS setIsReverse:] in AudioControllerBASS.o
      -[AudioControllerBASS setIsHighQuality:] in AudioControllerBASS.o
  "_BASS_FX_TempoCreate", referenced from:
      -[AudioControllerBASS setupBASS:] in AudioControllerBASS.o
  "_BASS_FX_ReverseCreate", referenced from:
      -[AudioControllerBASS setupBASS:] in AudioControllerBASS.o
ld: symbol(s) not found for architecture armv7
collect2: ld returned 1 exit status

Ian @ un4seen

Yes, the current BASS_FX build does not include support for armv7 (only armv6). An update will be available shortly, hopefully :)

ppeau

Thanks because XCode 4 is now released  8)

(: JOBnik! :)

Hi ;D

Here's an update 2.4.6.1 beta, that combines support for "armv6/7" architectures and simulator in one file.
http://www.jobnik.org/files/libbass_fx.a

mits

Hi JOBnik,

This beta file seems to work correctly :)

Build of my app succeeded with Xcode 4 and worked on iPhone 4.
I confirmed at least pitch and tempo control function.

Thanks!

Gurt87

Guys, how can i get effect like "Concert hall", "Subway", "Bar", "Sidewalk", etc.   with BASS library?

Serginho

Quote from: Gurt87Guys, how can i get effect like "Concert hall", "Subway", "Bar", "Sidewalk", etc.   with BASS library?

I'm working on the same issue. I've tried to user BASS_FX with different params, but with no results. Any help?

      hfxHandle = BASS_ChannelSetFX(chan, BASS_FX_DX8_FLANGER, 1);
      BASS_DX8_FLANGER bigAreaParams = { 500.0, 36.0, -15.0, 15.0f, 115, 15.0f, 115};
      BASS_FXSetParameters(hfxHandle, &bigAreaParams);