wav2sbc: convert wav format to txt format of SBC

Posted by tinyang on Thu, 23 Dec 2021 06:11:45 +0100

The local music of some Bluetooth audio devices needs to use the sbc format, such as the Bluetooth headset of hengxuan (BES). If you are engaged in the development of BES platform, you must know it very well. Their local audio uses the sbc format in the form of txt, and it is also the sbc format of mono 16 bit and 16KHz sampling rate

Realization idea

Because I usually use Unix systems, such as Macos and Ubuntu, I focus on how to realize this audio conversion on Unix platform. In fact, many tools with interface are simple to use, but I think the command tools are more efficient, especially in batch operation, As a technology house that doesn't like using the mouse very much, just use the command line if you can

I can think of two ideas:

  1. Find some open source code that wav encodes into sbc. These open source codes are basically implemented in C/C + +. Integrate these codes into your own project, such as the codec of ffmpeg, and then call these codec functions in C. But this implementation is very troublesome, especially for beginners of audio
  2. The second scheme is implemented by using the script. We know that ffmpeg is a very powerful audio and video processing software. We can directly call the ffmpeg command on the shell to realize the format conversion from wav to sbc, but we can't get the txt form of sbc. However, we can implement the following division of labor with the script. This scheme is very simple, And it can be realized without understanding audio knowledge

Environment installation

I am now using the Ubuntu environment, because Ubuntu does not install ffmpeg by default, but the installation command is also very simple

$ sudo apt-get install ffmpeg -y	

Let's check my test audio first

$ ffmpeg -i test.wav
Input #0, wav, from 'test.wav':
  Duration: 00:00:01.91, bitrate: 1536 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s

It can be seen that my audio file is a 48KHz sampling rate, dual channel, 16 bit format

Now you need to convert it into a 16KHz sampling rate, mono, 16 bit sbc file. The input command is as follows

$ ffmpeg -i test.wav -ar 16000 -ac 1 test.sbc
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_s16le (native) -> sbc (native))
Press [q] to stop, [?] for help
Output #0, sbc, to 'test.sbc':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Audio: sbc, 16000 Hz, mono, s16, 128 kb/s
    Metadata:
      encoder         : Lavc58.91.100 sbc
size=      30kB time=00:00:01.91 bitrate= 128.0kbits/s speed= 513x
video:0kB audio:30kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%

Let's check test Format of SBC

$ ffmpeg -i test.sbc
Input #0, sbc, from 'test.sbc':
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Audio: sbc, 16000 Hz, mono, s16

It is already a mono, 16KHz sampling rate, 16 bit sbc file

We will now continue to convert this sbc file to TXT format

#! /usr/bin/python

import sys
import os

input = "test.sbc"
# Read sbc file
with open(input, "rb") as f:
    content = f.read()

out = ""
# Convert it into TXT file in Hex form
for i in range(len(content)):
    if i % 16 == 0 and i != 0:
        out += "\n";
    out += "0x%02x," % ord(content[i])

output = os.path.splitext(input)[0] + ".txt"
# Output to file test txt
with open(output, "w+") as f:
    f.write(out)

print("done")

test.txt file is the file we want

Functional integration

Now let's integrate these two parts of work into a Python script

#! /usr/bin/python
#coding=utf-8

# Filename:  wav2sbc.py

import sys
import os

def transfer(input):
    # Read sbc file
    with open(input, "rb") as f:
        content = f.read()

    out = ""
# Convert it into TXT file in Hex form
    for i in range(len(content)):
        if i % 16 == 0 and i != 0:
            out += "\n";
        out += "0x%02x," % ord(content[i])

    output = os.path.splitext(input)[0] + ".txt"
# Output to file test txt
    with open(output, "w+") as f:
        f.write(out)

def wav2sbcHex(wavFilename):
    sbcFilename = os.path.splitext(wavFilename)[0] + ".sbc"
    cmd = "ffmpeg -i %s -ar 16000 -ac 1 %s" % (wavFilename, sbcFilename)
    os.popen(cmd)
    if os.path.isfile(sbcFilename):
        print("Wav Transfer sbc Successfully");
    else:
        print("Wav Transfer sbc Error")
        exit(1)

    transfer(sbcFilename)
    txtFilename = os.path.splitext(sbcFilename)[0] + ".txt"
    if os.path.isfile(txtFilename):
        print("Sbc Transfer Hex txt Successfully")
        print("Done")
    else:
        print("Sbc Transfer Hex txt Error")
        exit(1)

if __name__ == "__main__":
    for wavFilename in sys.argv[1:]:
        wav2sbcHex(wavFilename)

This script takes command line parameters as input and outputs the corresponding sbc file and txt file

$ ./wav2sbc.py test.wav
Wav Transfer sbc Successfully
Sbc Transfer Hex txt Successfully
Done

The above command generates test in the current directory SBC and test Txt file

If you want to realize batch conversion, it is also very simple. The following command can convert all wav files in the current directory at one time

$ ls *.wav | xargs ./wav2sbc.py

Topics: Python shell