store ulaw to pcm converted sound to a wave file

152 views Asked by At

I am trying to store a converted audio to a wave file and the file is not working correctly as it is not playing any sound and seems corrupted.

I first read a base64.txt as an ulaw audio and then convert it to pcm format afterward. The conversion seems fine as playing the audio works, but the writing to file is failing somehow. I tried some debugging and found out that the bytes written are way less than the actual audio stream contains.

This is the calculation I found in WaveFileWriter#write -> getAudioFileFormat :

fileSize = (int) stream.getFrameLength() * streamFormat.getFrameSize() + WaveFileFormat.getHeaderSize(waveType);

the getFrameLength is 659 and getFrameSize is 2 (see images)

enter image description here

enter image description here

which makes sense if you look at the code. Do I maybe have a wrong frameSize set in the pcmFormat? I tried others like 160 as well but all those gave me Unsupported conversion .

I am guessing that the problem is that the calculated file size is way smaller than the actual size of the stream and thus its only writing the data till that calculated file size. These are the outputs from print lines:

Available: 116480
Actually written: 1500

This is the main method:

    public static void main(String[] args) throws Exception {
        Path base64 = Path.of(Main.class.getResource("/base64.txt").toURI());
        byte[] decodedAudioBytes = Base64.getDecoder().decode(Files.readAllBytes(base64));

        ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedAudioBytes);
        AudioFormat audioFormat = new AudioFormat(
                AudioFormat.Encoding.ULAW,  // Audio format details here
                8000,
                8,
                1,
                160,
                50,
                false
        );
        AudioInputStream ulawAudioInputStream = new AudioInputStream(inputStream, audioFormat, decodedAudioBytes.length / audioFormat.getFrameSize());
        AudioFormat ulawFormat = ulawAudioInputStream.getFormat();
        AudioFormat pcmFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,
                ulawFormat.getSampleRate(),
                16, // 16-bit sample size
                ulawFormat.getChannels(),
                ulawFormat.getChannels() * 2, // Frame size
                ulawFormat.getSampleRate(),
                false // Little endian
        );

        try (inputStream; ulawAudioInputStream; AudioInputStream pcmAudioInputStream = AudioSystem.getAudioInputStream(pcmFormat, ulawAudioInputStream)) {

//        playAudio(pcmAudioInputStream, pcmAudioInputStream.getFormat());

            System.out.println("Available: " + pcmAudioInputStream.available());
            System.out.println("Actually written: " + AudioSystem.write(pcmAudioInputStream, AudioFileFormat.Type.WAVE, Files.newOutputStream(Path.of("D://test.wav"), StandardOpenOption.CREATE)));
        }
    }

    private static void playAudio(AudioInputStream audio, AudioFormat format) throws Exception {
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
        line.open(format);
        line.start();
        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = audio.read(buffer)) != -1) {
            line.write(buffer, 0, bytesRead);
        }
    }

with this base64.txt (be careful its kinda loud and just an example audio):

https://gist.github.com/SquidXTV/4a696ef4d714cf0043727ae4c141e8f3

thanks for your help

0

There are 0 answers