BASS Channel Decoding

Started by big_gun,

big_gun

I use VB.NET (nBASS) and VB6, and am having a small problem.

If you rip a audio cd track from Goldenhawk (CDRWIN) and choose "RAW and CD+G" options, it creates a .bin file. The bin file is interleaved raw pcm data (2352 bytes) and subcode information (96 bytes)

I've been able to create software that splits these into two files (raw pcm and subcode), and encode the raw file to an mp3.

What I am currently having a problem with is decoding the mp3 channel to raw pcm data. I am using bass_init with the leavevolume flag, and then setting the position to 0 with channelsetposition. then I am doing something like this:

Dim a as integer
Dim FileBytes1(2352) as byte ' Array of bytes
Dim BW as system.io.binarywriter = new system.io.binarywriter("temp.raw")
Dim Filesize as long = stream.length

For a = 0 to filesize step 2352
                 retval = strm.GetData(FileBytes1, 2352)
                 BW.write(FileBytes)
next
BW.close

The problem is when the file is created, the temp.raw file is not 16 bit raw PCM data. it does not match what the bin file is. The size is also different (larger).

Bin files are evenly divided by 2448 (2352 raw PCM + 96 subcode). The raw file is evenly divided by 2352. The output file I create with the source above is larger than it should be.

When I use VB6 to do it (bass 1.7) I get different results, the file size is smaller than it should be, and is not standard raw PCM data.

Please help!

Ian @ un4seen

QuoteWhat I am currently having a problem with is decoding the mp3 channel to raw pcm data. I am using bass_init with the leavevolume flag
Just a little tip... if you're only decoding (ie. not playing anything), then you could use the "no sound" device when you call BASS_Init. That way it can run even without a soundcard :)

QuoteFor a = 0 to filesize step 2352
                retval = strm.GetData(FileBytes1, 2352)
                BW.write(FileBytes)
next
This would be better...
while (strm.ActivityState != State.Stopped)
      retval = strm.GetData(FileBytes1, 2352)
      BW.write(FileBytes1, retval)
wend
I don't know if that's correct vb.net syntax, but you get the idea :)
QuoteThe problem is when the file is created, the temp.raw file is not 16 bit raw PCM data. it does not match what the bin file is. The size is also different (larger).
MP3 encoding is lossy, so it's not going to be exactly the same as the original data. The result is also very unlikely to be exactly the same size as the original, as MP3 encoding adds a bit of padding at the start and end.

big_gun

I guess my post was slightly off. What I did not say was that the output raw data was not playable in sound forge as (raw). Apparently it is not the same as raw 16 bit pcm signed data.

Thanks for the code update. The only difference is that := or != is only = in VB.net and no semi colons.

Rick

big_gun

I implemented your changes, and it works better than my code.

However, the file is still unplayable.

Do I have to convert from signed to unsigned or something?

How do I get this to raw pcm data?

Ian @ un4seen

QuoteDo I have to convert from signed to unsigned or something?
No conversion should be required, as the data you receive from BASS_ChannelGetData is standard signed 16-bit PCM data.

Upload - ftp://ftp.un4seen.com/incoming/ - the first few K of the MP3 and output RAW files, and I'll see if I can spot anything. You could also post the exact code you use to initialize BASS, create the stream, and decode the data.

big_gun

I figured it out!

For all those using VB.NET or CSharp.NET, here is a tip when decoding files:

If you write the array instead of each byte the file will be corrupt.

Complete source to decode mp3 to raw file in VB.NET with nBass:

    Private Sub WriteRaw(ByVal InFile As String, ByVal OutFile As String)
        ' nBass Declares
        Dim BA As New nBASS.BASS(-2, 44100, nBASS.DeviceSetupFlags.LeaveVolume, Me.Handle)
        Dim sLen As Integer = CType(FileLen(InFile), Integer)
        Dim strm As nBASS.Stream = BA.LoadStream(False, InFile, 0, 0, nBASS.StreamFlags.DecodeOnly)
        ' File Streams
        Dim FS As FileStream = New FileStream(OutFile, FileMode.OpenOrCreate)
        Dim BW As BinaryWriter = New BinaryWriter(FS)
        ' Other Misc. Declarations
        Dim RawPad As Integer = 2352
        Dim RetVal As Integer
        Dim T(RawPad) As Byte
        Dim sPos As Integer
        Dim a As Integer


        Do While strm.ActivityState = nBASS.State.Playing
            RetVal = strm.GetData(T, RawPad)
            If RetVal = RawPad Then
                ' This was the problem. If you BW.Write(T) ' The whole array
                ' The file will be corrupt.
                ' Write one byte at a time.
                For a = 0 To RawPad - 1
                    BW.Write(T(a))
                Next

                'Write the progress percentage to the label control
                sPos = strm.GetFilePosition(nBASS.Stream.Mode.Decoding)
                Label1.Text = Percentage(sPos, sLen).ToString + "%"
                ' Don't hog the CPU
                Application.DoEvents()
            End If
        Loop
        BW.Close()
        FS.Close()

        BA.Dispose()
    End Sub

    Private Function Percentage(ByVal IntDone As Integer, ByVal IntMax As Integer) As Int16
        Dim D As Int16

        D = CType(100 * IntDone / IntMax, System.Int16)
        If D > 100 Then D = 100
        Return D
    End Function