Author Topic: Direct Stream Digital (DSD) add-on  (Read 27869 times)

Ian @ un4seen

  • Administrator
  • Posts: 20389
Direct Stream Digital (DSD) add-on
« on: 27 Oct '14 - 17:46 »
There have been requests for DSD support in BASS, so here's a little add-on that adds that...

Now available on the BASS page.


All DSD rates (including 48KHz variants like 3.072MHz) should be supported, in DSDIFF and DSF containers. DST encoding is not supported. ID3v2 tags (BASS_TAG_ID3V2) are supported in DSF files, and DSDIFF comments (BASS_TAG_DSD_COMMENT) are also supported. As well as local files, internet streams and user file streams are supported.

DSD can be converted to PCM at various sample rates (44100/88200/176400/352800), which BASSDSD supports via the BASS_DSD_StreamCreateFile/User "freq" parameter. There is also a BASS_CONFIG_DSD_FREQ config option (default is currently 88200), which applies when the plugin system is used or when the "freq" parameter is set to 0. The requested rate will automatically be rounded-up to the nearest valid rate, eg. 44100 would be rounded-up to 48000 for a 48KHz variant DSD file. DSD encoding is 6dB quieter than PCM, so BASSDSD will raise the level by 6dB by default. That can be changed via the BASS_CONFIG_DSD_GAIN config option before stream creation, and the BASS_ATTRIB_DSD_GAIN attribute after stream creation.

The data can also be kept in DSD form, for playback on devices that support DSD. The BASS_DSD_RAW flag produces raw DSD data in 8 sample/bit blocks with MSB 1st (as in DSDIFF files), which can be played by DSD-supporting ASIO driver/devices (a BASSASIO update with DSD support is also included). The BASS_DSD_DOP flag produces DSD-over-PCM data, which can be played on devices that support that via any bit-perfect output system, eg. ASIO or exclusive-mode WASAPI.

Please report any problems encountered.
« Last Edit: 17 Dec '14 - 14:22 by Ian @ un4seen »

3delite

  • Posts: 895
Re: Direct Stream Digital (DSD) add-on
« Reply #1 on: 27 Oct '14 - 17:52 »
Cool! I'll test it in the following days. Thank you!

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #2 on: 28 Oct '14 - 15:30 »
OSX and Linux builds are now included in the package in the 1st post.

3delite

  • Posts: 895
Re: Direct Stream Digital (DSD) add-on
« Reply #3 on: 28 Oct '14 - 22:38 »
Quick test shows no problems, tried with some DFF and DSF files. Nice work.

Is it possible to add some kind of info query option to get the file's resolution (1/8bit)? Maybe a flag for ctype? And original (file's) sample rate?
Wikipedia page mentions that there are Double-rate DSD (DSD128), Quad-rate DSD (DSD256) and Octuple-rate DSD (DSD512) formats, are these supported by BASSDSD?

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #4 on: 29 Oct '14 - 16:40 »
Yes, all of those DSD rates should be supported. An updated BASSDSD version is now up in the 1st post, which adds a BASS_ATTRIB_DSD_RATE attribute (read-only) to get the file's rate. For example, it could be used to display the format as DSD64/128/etc something like this...

Code: [Select]
BASS_CHANNELINFO ci;
BASS_ChannelGetInfo(handle, &ci);
if (ci.ctype==BASS_CTYPE_STREAM_DSD) { // it's a DSD stream
float rate;
BASS_ChannelGetAttribute(handle, BASS_ATTRIB_DSD_RATE, &rate); // get the rate
printf("format = DSD%d\n", (int)rate/44100); // display it
}
« Last Edit: 30 Oct '14 - 14:09 by Ian @ un4seen »

3delite

  • Posts: 895
Re: Direct Stream Digital (DSD) add-on
« Reply #5 on: 29 Oct '14 - 22:29 »
Thank you very much! Seems working just fine! :)

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #6 on: 30 Oct '14 - 14:10 »
Jolly good. Let me know if that changes :)

By the way, the BASS_ATTRIB_DSD_FREQ attribute has now been renamed to BASS_ATTRIB_DSD_RATE to make it clearer that it's unrelated to the BASS_CONFIG_DSD_FREQ option (like BASS_ATTRIB_DSD_GAIN and BASS_CONFIG_DSD_GAIN are related).

3delite

  • Posts: 895
Re: Direct Stream Digital (DSD) add-on
« Reply #7 on: 30 Oct '14 - 21:29 »
Okay. :)

stevenmmm

  • Posts: 114
Re: Direct Stream Digital (DSD) add-on
« Reply #8 on: 31 Oct '14 - 09:18 »
No problems with playing any of the files i have tested or users have tested.
However I did get one comment:
"it will play the DSF files, but my DAC (Geek OUT 450) is not recognizing the file as a DSD file"
I understand that to mean that the DSD file is getting converted to PCM and sent to the device as PCM data. Am I correct in understanding some devices can decode DSD natively and if so, is there any way my application can detect this and/or instruct bass to play the file undecoded? Is there a good reason a user would want that eg. perhaps much less data is sent to the device?
And secondly this guy also made this claim:
"Samplerate should be 2.8MHz for DSD64 and 5.6MHz for DSD128"
the sample rate is being set to 88.2 and i understand it can be changed using BASS_CONFIG_DSD_FREQ but is this claim correct?

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #9 on: 31 Oct '14 - 16:38 »
BASSDSD currently always converts the DSD data to PCM (BASS_CONFIG_DSD_FREQ sets the PCM sample rate). There are some ASIO devices/drivers that can play DSD data, and I'm looking into the possibility of adding support for that in BASSASIO and then adding a DSD output option to BASSDSD, ie. the DSD data would be played via BASSASIO. I'll post an update here if that comes to be.

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #10 on: 6 Nov '14 - 17:07 »
BASS DSD addon is ok in my player ASIO by AVX instruction set.
Thank you.

PureBasic 5.30

Code: [Select]
; Import BASS DSD Add-on
;
; Additional BASS_SetConfig options
#BASS_CONFIG_DSD_FREQ = $10800
#BASS_CONFIG_DSD_GAIN = $10801
;
; BASS_CHANNELINFO Type
#BASS_CTYPE_STREAM_DSD = $11700
;
; Additional attributes
#BASS_ATTRIB_DSD_GAIN = $14000
#BASS_ATTRIB_DSD_RATE = $14001
;
Import "bassdsd.lib"
  BASS_DSD_StreamCreateFile.l(mem.b, *file, offset.q, length.q, flags.l, freq.l)
  BASS_DSD_StreamCreateFileUser.l(system.l, flags.l, *procs, *user, freq.l)
EndImport
; End Import BASS DSD Addon

Code: [Select]
chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_SAMPLE_FLOAT | #BASS_SAMPLE_SOFTWARE , 0)
« Last Edit: 7 Nov '14 - 02:55 by Oryaaaaa »

lqbe

  • Posts: 32
Re: Direct Stream Digital (DSD) add-on
« Reply #11 on: 8 Nov '14 - 02:44 »
Working well so far!

I'm looking into the possibility of adding support for that in BASSASIO and then adding a DSD output option to BASSDSD,
ie. the DSD data would be played via BASSASIO. I'll post an update here if that comes to be.
That sounds pretty damn excellent.

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #12 on: 9 Nov '14 - 08:11 »
Bug? plase check follows this 4 bytes.

DSD128 decode by 44.1kHz is ok
DSD128 decode by 88.2kHz is ok
DSD128 decode by 176.4kHz is error at end of BASS_ChannelGetData

176.4kHz is Float data, But decode data % 8 = 4  then error

and Play by decode data - 4 is ok

Code: [Select]
If dataSize%8>0
  dataSize - dataSize%8 ; -4
EndIf

Sample DSD128
http://www.2l.no/
Mozart: Violin concerto in D major - Allegro
Marianne Thorsen / TrondheimSolistene
Stereo DFF DSD 128 5.6448Mbit/s
9:24   MOZART (2L-038-SACD)

Thank you.
« Last Edit: 9 Nov '14 - 10:20 by Oryaaaaa »

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #13 on: 10 Nov '14 - 15:16 »
I am getting an invalid length (not on a sample boundary) from BASS_ChannelGetLength with that file, but not a crash when decoding it. An update that should give the correct length is now up in the 1st post. Let me know if you still get the crash with it.

This update also adds a couple of DSD output options. The BASS_DSD_DOP flag produces DSD-over-PCM data for devices that support that (it'll be low level noise on non-supporting devices). DoP data is 24-bit, so the BASS_SAMPLE_FLOAT flag is also needed. Note that the data will need to be played bit-perfectly, eg. via ASIO or exclusive-mode WASAPI, and no DSP should be applied. For example, it could be used something like this with BASSWASAPI...

Code: [Select]
dsd=BASS_DSD_StreamCreateFile(FALSE, filename, 0, 0, BASS_DSD_DOP|BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE, 0); // open a DSD file in DoP mode
BASS_CHANNELINFO ci;
BASS_ChannelGetInfo(dsd, &ci); // get the sample format
BASS_WASPAPI_Init(-1, ci.freq, ci.chans, BASS_WASAPI_EXCLUSIVE, 0.4, 0, WasapiProc, 0); // initialize the output device

...

DWORD CALLBACK WasapiProc(void *buffer, DWORD length, void *user)
{
int r=BASS_ChannelGetData(dsd, buffer, length); // get data from the DSD stream
if (r==-1) r=0;
return r;
}

The BASS_DSD_RAW flag produces raw DSD data in 8 sample/bit blocks with MSB 1st, the same as in DSDIFF files. As the data isn't PCM, so not playable by BASS, the BASS_STREAM_DECODE flag must be used (to create a decoding channel) and it isn't supported via the plugin system (BASS_DSD_StreamCreateFile/User must be used). A BASSASIO update is also provided to play the DSD data; it adds a BASS_ASIO_SetDSD function to switch between DSD and PCM modes on DSD supporting drivers/devices. It could be used something like this...

Code: [Select]
BASS_ASIO_SetDSD(TRUE); // switch the ASIO device to DSD mode
dsd=BASS_DSD_StreamCreateFile(FALSE, filename, 0, 0, BASS_DSD_RAW|BASS_STREAM_DECODE, 0); // open a DSD file in RAW mode
float rate;
BASS_ChannelGetAttribute(dsd, BASS_ATTRIB_DSD_RATE, &rate); // get the DSD rate
BASS_ASIO_SetRate(rate); // set the device to that rate
BASS_CHANNELINFO ci;
BASS_ChannelGetInfo(dsd, &ci); // get the sample format (for channel count)
BASS_ASIO_ChannelEnable(0, 0, AsioProc, 0); // enable 1st output channel...
for (int a=1; a<ci.chans; a++)
BASS_ASIO_ChannelJoin(0, a, 0); // and join the next channels to it
BASS_ASIO_ChannelSetFormat(0, 0, BASS_ASIO_FORMAT_DSD_MSB); // set the data format (DSD with MSB 1st)

...

DWORD CALLBACK AsioProc(BOOL input, DWORD channel, void *buffer, DWORD length, void *user)
{
int r=BASS_ChannelGetData(dsd, buffer, length); // get data from the DSD stream
if (r==-1) r=0;
return r;
}

You should of course check return values in real code, particularly BASS_ASIO_SetDSD and BASS_ASIO_SetRate to confirm that the device supports DSD at the required rate. There are a few things that aren't available when an ASIO driver is in DSD mode: there's no resampling (BASS_ASIO_ChannelSetRate), no volume control (BASS_ASIO_ChannelSetVolume), and no level retrieval (BASS_ASIO_ChannelGetLevel).

This new stuff hasn't been tested much, so if you try it, please report how you get on.

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #14 on: 11 Nov '14 - 04:46 »
DSD64 and DSD128 format is OK by native ASIO.
* But DSD256 format didn't load by BASS_DSD_StreamCreateFile(#BASS_DSD_RAW).

DSD128(PCM 176.4kHz) length problem is OK.

Thank you.

PureBasic 5.30  32-bit 64-bit
Code: [Select]
...
#BASS_ASIO_FORMAT_DSD_LSB = 32 ; DSD (LSB 1st)
#BASS_ASIO_FORMAT_DSD_MSB = 33 ; DSD (MSB 1st)

Import "bassasio.lib"
  ...
  BASS_ASIO_SetDSD.b(dsd.b)
  BASS_ASIO_Future.b(selector.l, *param)
EndImport

Code: [Select]
Case "DSF","DFF"
  If MusicFileCheck(FileName)
    Select dsd_play
      Case 0
        chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_SAMPLE_FLOAT | #BASS_SAMPLE_SOFTWARE , dsd_freq)
        Debug "DSD PCM"
      Case 1
        chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_DSD_RAW | #BASS_SAMPLE_SOFTWARE , 0)
        Debug "DSD RAW"
    EndSelect
  EndIf
  

Code: [Select]
If BASS_ASIO_Init(AsioSelectDevice, #BASS_ASIO_THREAD) And BASS_ASIO_SetDSD(#True) And BASS_ASIO_CheckRate(dsd_max_freq)
  BASS_ChannelGetAttribute(chan, #BASS_ATTRIB_DSD_RATE, @dsd_check_freq); // get the DSD rate
  BASS_ASIO_SetRate(dsd_check_freq) : dsd_now_freq = dsd_check_freq
  SetGadgetText(#Radio_Freq, StrF(dsd_now_freq/1000000,2)+"MHz")
  BASS_ASIO_ChannelEnable(0,Int(AsioChShift),@AsioProc(), 0)
  BASS_ASIO_ChannelJoin(0,Int(AsioChShift+1),Int(AsioChShift))
  BASS_ASIO_ChannelSetFormat(0, 0, #BASS_ASIO_FORMAT_DSD_MSB); // set the data format (DSD with MSB 1st)
  BASS_ASIO_Start(0, 0)
« Last Edit: 11 Nov '14 - 05:06 by Oryaaaaa »

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #15 on: 11 Nov '14 - 17:06 »
* But DSD256 format didn't load by BASS_DSD_StreamCreateFile(#BASS_DSD_RAW).

Is there a particular DSD256 file that isn't working? If so, please post a link to it or upload it (the first 10MB will suffice) here...

   ftp.un4seen.com/incoming/

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #16 on: 12 Nov '14 - 01:18 »
* But DSD256 format didn't load by BASS_DSD_StreamCreateFile(#BASS_DSD_RAW).

Is there a particular DSD256 file that isn't working? If so, please post a link to it or upload it (the first 10MB will suffice) here...

   ftp.un4seen.com/incoming/

upload file : nap_DSD256.zip  122MB  1 min

Sample URL (DSD256, DSD512): (Dozing)(DSDIFF,DSD256)
http://wechdomi.org/english/index.html
* ADC:ElectrArt DSD256 Recorder

Code: [Select]
FileName.s = "nap_DSD256.dff" ; (Dozing)(DSDIFF,DSD256)

Case "DSF","DFF"
  Select dsd_play
    Case 0
      chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_SAMPLE_FLOAT | #BASS_SAMPLE_SOFTWARE , dsd_freq)
      Debug "DSD PCM  "+Str(chan) ; Return handle , OK
    Case 1
      chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_DSD_RAW | #BASS_SAMPLE_SOFTWARE , 0)
      Debug "DSD RAW  "+Str(chan) ; Retrun 0 , Error
  EndSelect
« Last Edit: 12 Nov '14 - 01:24 by Oryaaaaa »

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #17 on: 12 Nov '14 - 16:40 »
I don't seem to be able to reproduce the problem here (the uploaded file seems to be working fine), so that's strange. What is the error code from the failed BASS_DSD_StreamCreateFile call, ie. what does BASS_ErrorGetCode report?

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #18 on: 12 Nov '14 - 17:51 »
I don't seem to be able to reproduce the problem here (the uploaded file seems to be working fine), so that's strange. What is the error code from the failed BASS_DSD_StreamCreateFile call, ie. what does BASS_ErrorGetCode report?

I see.

Code: [Select]
BASS_Init(0, freqS,#BASS_DEVICE_NOSPEAKER,WindowID(#Window),#Null)  : BASS_SetDevice(0)
Code: [Select]
chan =  BASS_DSD_StreamCreateFile(#False, @FileName, 0, 0, #BASS_UNICODE | #BASS_STREAM_DECODE  | #BASS_DSD_RAW | #BASS_SAMPLE_SOFTWARE , 0)
Debug "DSD RAW  "+Str(chan)
Debug BASS_ErrorGetCode()

Quote
DSD RAW  0
6
DSD RAW  0
6
DSD RAW  0
6

BASS_ERROR_FORMAT   6   // unsupported sample format
« Last Edit: 12 Nov '14 - 18:01 by Oryaaaaa »

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #19 on: 12 Nov '14 - 18:18 »
Oh yes, I see it now. I hadn't noticed it previously because my test code was retrying without the BASS_DSD_RAW flag if it failed. The problem is actually caused by a 1000000 Hz sample rate limit imposed by BASS at stream creation (BASS_ATTRIB_FREQ can go higher). I'll post a BASS update with a raised limit tomorrow, along with a BASSDSD update that fixes some other little things (regarding incomplete DSD files).

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #20 on: 13 Nov '14 - 15:51 »
Here's the aforementioned BASS update...

   www.un4seen.com/stuff/bass.zip

It raises the maximum accepted sample rate at stream creation to 10000000 Hz. An updated BASSDSD version is also up in the 1st post, which fixes a couple of issues with incomplete DSD files, eg. correct length reporting.

stevenmmm

  • Posts: 114
Re: Direct Stream Digital (DSD) add-on
« Reply #21 on: 17 Nov '14 - 20:12 »
can anyone confirm they have this working for playing a raw DSD file?
The first problem i had was the asio checkrate function always returned false for the sample rate of the DSD file (also using the newest bass.dll). So removing that check and the user reported: "only hear white noise, and my DAC reports the incoming file is 352.8 khz PCM"
The same files played by foobar apparently work ok as raw DSD.
I realise it may easily be a bug on my part but i cannot see what the bug would be so it would be helpful before spending too much time to know if others have it working
edit:
perhaps BASS_ASIO_SetDSD(true) is required to be done before channels are joined, and the channels reset/rejoined if the BASS_ASIO_SetDSD needs to be changed?
« Last Edit: 18 Nov '14 - 08:34 by stevenmmm »

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Direct Stream Digital (DSD) add-on
« Reply #22 on: 18 Nov '14 - 15:23 »
Are you using the same code as I posted, and are all of the BASSASIO calls reporting success in their return values? Please also check what the output channel's sample format is after the BASS_ASIO_SetDSD call, via BASS_ASIO_ChannelGetInfo.

BASS_ASIO_SetDSD currently only resets the channel sample format and rate, overriding BASS_ASIO_ChannelSetFormat and BASS_ASIO_ChannelSetRate settings. The other channel settings (eg. joins) are retained.

stevenmmm

  • Posts: 114
Re: Direct Stream Digital (DSD) add-on
« Reply #23 on: 19 Nov '14 - 21:41 »
@ian, yes i am following your example although i cant implement exactly in that same straight-forward sequence because there are other scenarios such as playing a non-DSD file before hand and the need to incorporate into existing functionality. So i am starting off by initialising the device assuming normal playback and only switching to native DSD when a DSD file is being played, so the calls are being made after the channels are initialised/ joined. But i have checked all the same calls are being made (there was a stupid typo where SetDSD was set to false) - the file is being reported as a DSD file on the device but still plays with white noise.
the only things i can see is I am doing extra is using BASS_ASIO_ChannelSetRate() as a fallback to BASS_ASIO_SetRate so i will try removing that for DSD files to see if it helps
edit: i realise now what it probably is - i am initially joining all channels as presented as being available by the device and what i need to do is reset the channels to the number of channels that are in the source file.
« Last Edit: 20 Nov '14 - 11:35 by stevenmmm »

Oryaaaaa

  • Posts: 40
Re: Direct Stream Digital (DSD) add-on
« Reply #24 on: 19 Nov '14 - 22:50 »
It raises the maximum accepted sample rate at stream creation to 10000000 Hz. An updated BASSDSD version is also up in the 1st post, which fixes a couple of issues with incomplete DSD files, eg. correct length reporting.

Thank you.

DSD256,DSD512 of support DAC test results are not reported.

dsd output demo by bass [6.72MB]
deleted url
---
include [video 5min] How to play dsd.wmv
include 32-bit, 64-bit
Required MMX,SSE2,AVX
« Last Edit: 11 Feb '17 - 18:35 by Oryaaaaa »