Author Topic: DSPPROC and RECORDPROC size  (Read 700 times)

rdkartono

  • Posts: 30
DSPPROC and RECORDPROC size
« on: 25 Apr '19 - 10:50 »
Dear all,

I know how to use DSPPROC and RECORDPROC , but I want to know how to make them trigger every 1024 bytes ?

Here is the problem background :
I am dealing with some audio device that need very accurate timing.
It use PCM 16bit , mono, 48Khz.
If calculated , 48Khz x (16/8) x 1 (mono) then we have 96.000 bytes.
the device requires that we send each packet 1024 bytes constantly, at precise timing.
If calculated, 96000 bytes / 1024 bytes/packet = 93.75 packet / second .
Then each packet interval should be 1000ms / 93.75 =  10.666666 miliseconds.

Current situation :
I develop my code using Java, and unluckily Thread.sleep is not accurate.
If i use busy loop and System.nanotime() on PC, I can reach almost perfect streaming.. in cost of High CPU usage.
But I can not use this method on Android app, as it perform more inconsistent than PC.

So back to question :
Can I ask BASS to trigger above procs every 1024 bytes ?
If i read at manual, BASS_CONFIG_BUFFER is set using milisecond value, not byte size value.

Hope somebody can help. Thanks.

Ian @ un4seen

  • Administrator
  • Posts: 22121
Re: DSPPROC and RECORDPROC size
« Reply #1 on: 25 Apr '19 - 13:50 »
Is the DSPPROC set on the recording channel? If so, it will be called just before the RECORDPROC function is (on the same data). Regarding processing 1024 bytes at a time, you can achieve that by removing the RECORDPROC function and instead using BASS_ChannelGetData to fetch the recorded data in a worker thread or timer (the DSPPROC will then be called within BASS_ChannelGetData). You can use the BASS_DATA_AVAILABLE flag first to check that the required amount of data (ie. 1024 bytes) is available. Here's an example of doing that sort of thing:

   www.un4seen.com/forum/?topic=18448

rdkartono

  • Posts: 30
Re: DSPPROC and RECORDPROC size
« Reply #2 on: 25 Apr '19 - 16:08 »
DSPPROC is used in StreamCreateFile handle. I Bass_init on device 0 (no sound), then streamcreaStream, then ChannelPlay, then ChannelSetDSP.

For recording channel , i used RECORDPROC, but I will revise my code based on your recommendation.

Back to DSPPROC again, actually after ChannelPlay, I also ChannelSetAttribute to it, at BASS_ATTRIB_BUFFER value 0. This give 10ms DSPPROC callbacks with 960bytes.
I want to know if this can be set to 1024 bytes per callback.

Ian @ un4seen

  • Administrator
  • Posts: 22121
Re: DSPPROC and RECORDPROC size
« Reply #3 on: 25 Apr '19 - 17:13 »
At what point are you sending the data to the output device? Is that what the DSPPROC is doing? If so, perhaps you can set the BASS_STREAM_DECODE flag on the stream instead to make it a "decoding channel" and then repeatedly call BASS_ChannelGetData on it to feed the output, similar to the recording channel case.

rdkartono

  • Posts: 30
Re: DSPPROC and RECORDPROC size
« Reply #4 on: 25 Apr '19 - 23:06 »
Sorry for late reply. For using BASS_STREAM_DECODE , I have tried before using procs, of course i can get buffer size as much as i want  immediately.  But as I told before, it's difficult for android to maintain constant 10.6 ms interval send... PC is achievable by busy loop but sacrificing CPU usage.

So that's why I tried to use DSPPROC in playback , hoping I can use hardware playback timing in consuming PCM bytes.
If only you can help configure BASS to use hardware playback timing, and trigger interval based on buffer size (currently only available in millisecond values), then this problem will be solved... I think...  ;)

Ian @ un4seen

  • Administrator
  • Posts: 22121
Re: DSPPROC and RECORDPROC size
« Reply #5 on: 26 Apr '19 - 12:29 »
I don't think it will be possible to guarantee a callback exactly every 10.6ms. Are you sure you actually need that? Usually, double buffering would be used to allow some leeway. For example, that's how ASIO and exclusive-mode WASAPI work on Windows.

The latest Android BASS version does actually have the option of setting the output device period in samples instead of milliseconds by setting the BASS_CONFIG_DEV_PERIOD option to a negative number, eg. -512 = 512 samples. But that won't mean that your DSPPROC callback will be at an exactly constant interval. If you would like to try it anyway, you can get it from here:

   www.un4seen.com/stuff/bass-android-test.zip

rdkartono

  • Posts: 30
Re: DSPPROC and RECORDPROC size
« Reply #6 on: 26 Apr '19 - 15:28 »
Thanks Ian, I will give it a try on Monday.
Does this setting also affect on RECORDPROC?

Ian @ un4seen

  • Administrator
  • Posts: 22121
Re: DSPPROC and RECORDPROC size
« Reply #7 on: 26 Apr '19 - 16:03 »
No, the BASS_CONFIG_DEV_PERIOD setting doesn't affect recording. There isn't currently any way to request a fixed amount of data in each RECORDPROC callback, so the BASS_ChannelGetData call in a worker thread method (mentioned above) would need to be used for that.

rdkartono

  • Posts: 30
Re: DSPPROC and RECORDPROC size
« Reply #8 on: 29 Apr '19 - 06:55 »
I thought your suggestion about double buffering during weekend, and came up with some ideas.
This Monday, implemented them, and surprisingly work very good.
Previously when it was failed, I use a relatively big ByteBuffer, around 1 MB size, and a thread+sleep to managed it.
Now I use a small ByteBuffer , 2 KB size, and no thread. But this buffer is changing quickly along with DSPPROC (on file playback) and ChannelGetData (on microphone recording), so playback / recording timing from BASS still a big help in here.

I haven't use "bass-android-test.zip", but very happy with current result.
Thank you Ian  ;D