Skip to content

02 ‐ foxAudioDecoder

Foxenfurter edited this page Mar 1, 2024 · 16 revisions

Overview

The decoder is designed to run in 2 stages. The Initialise process is deliberately separated from the Decoding process as this will allow the Header to be read as part of the setup and the Decoder to be run in the body of the code and therefore take advantage of GO's channels and pipeline architecture.

NB: the code is alpha, so the structure is subject to change

Initialise

Will read the header based upon the file type and source (File, stdin, Stream), and populate data in this structure

Associated Structure: AudioDecoder
Parameters: None
Returns: Error
type AudioDecoder struct {
	SampleRate  int`
	BitDepth    int
	NumChannels int
	Size        uint32 // Size of the audio data
	Type        string
	Filename    string // Added for file reading
	WavDecoder  *foxWavReader.WavReader
	FrameSample int
	DebugFunc   func(string) // enables the use of an external debug function supplied at the application level - expect to use foxLog

}
  • SampleRate - SampleRate of the incoming stream
  • BitDepth - Bit Depth of the incoming stream
  • NumChannels - Number of Audio Channels in the incoming stream, not to be conflated with Go Channels
  • Size - Data size. This should be the size of the audio signal and should exclude header and meta data
  • Type - At the moment only WAV is supported, it should be a simple matter to extend this to PCM. Other types may be added if required.
  • Filename - It is possible to read a file directly rather than from Stdin or an existing bytestream. If this is the case the source Filename should be
  • supplied
  • WavDecoder - assign the decoder to be used. At the moment I am not sure whether to have a different field for each decoder type or one generic one.
  • FrameSample - Size of a single sample across multiple channels taking into account the BitDepth
  • DebugFunc - Function used for Debugging. It is therefore possible to use different debug loggers and the default one, which only prints to screen.

Example usage:

package examplePackage

import (
"fmt"
foxAudioDecoder "github.com/Foxenfurter/foxAudioLib/foxAudioDecoder"
)

//Incomplete function,  used for illustration
func example() {
myDecoder := &foxAudioDecoder.AudioDecoder{
		Filename: "E:\\AudioTestFiles\\Resolution\\Pencil_24192.wav",
		Type: "Wav",
	}
	fmt.Println("Test: Decoding input file... ", myDecoder .Filename)
//*** Initialise HERE! ***
	err := myDecoder.Initialise()
	if err != nil {
		println("Test: Error initializing AudioDecoder: %v", err)
	}
//... Rest of function
}

DecodeSamples

Will call a lower level decoder (e.g. Wav ) and run independently of the Header. It is designed to operate in a pipelined Structure.

Associated Structure: AudioDecoder
Parameters: DecodedSamplesChannel chan [][]float64, ThrottleLoaderChannel chan time.Duration
Returns: Error

**DecodedSamplesChannel **is the GO Channel used to send Decoded Samples ([][]float64 - which means 1-n audio channels) to downstream processes. To take advantage of GO features this Channel should be buffered for example with a value of 1000, this will allow the load to continue without being held up by slower downstream processes. ThrottleLoaderChannel initial versions of the decoder had issues with buffering, where portions of the buffer were being overwritten before down-stream processes had read them. The ThrottleLoaderChannel was used to apply back-pressure to the loader in the form of a delay to apply before iterating. It is not required in the current version of the loader, but has been left in place for potential future file types. The code will function if a nil value is supplied.

Example Usage

\\ continued from previous example
var WG sync.WaitGroup
	DecodedSamplesChannel := make(chan [][]float64, 10000)
	WG.Add(1)
	go func() {
		defer WG.Done()
		myDecoder.DecodeSamples(DecodedSamplesChannel, nil)
	}()
\\ Rest of Function...

Clone this wiki locally