aiff

package
v0.0.0-...-c5379f9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2024 License: MIT Imports: 8 Imported by: 5

Documentation

Overview

Package aiff is a AIFF/AIFC decoder and encoder. It extracts the basic information of the file and provide decoded frames for AIFF files.

This package also allows for quick access to the AIFF LPCM raw audio data:

    in, err := os.Open("audiofile.aiff")
    if err != nil {
    	log.Fatal("couldn't open audiofile.aiff %v", err)
    }
	d := NewDecoder(in)
    frames, err := d.Frames()
    in.Close()

A frame is a slice where each entry is a channel and each value is the sample value. For instance, a frame in a stereo file will have 2 entries (left and right) and each entry will have the value of the sample.

Note that this approach isn't memory efficient at all. In most cases you want to access the decoder's Clip. You can read the clip's frames in a buffer that you decode in small chunks.

Finally, the encoder allows the encoding of LPCM audio data into a valid AIFF file. Look at the encoder_test.go file for a more complete example.

Currently only AIFF is properly supported, AIFC files will more than likely not be properly processed.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	COMMID = [4]byte{'C', 'O', 'M', 'M'}
	SSNDID = [4]byte{'S', 'S', 'N', 'D'}

	// ErrFmtNotSupported is a generic error reporting an unknown format.
	ErrFmtNotSupported = errors.New("format not supported")
	// ErrUnexpectedData is a generic error reporting that the parser encountered unexpected data.
	ErrUnexpectedData = errors.New("unexpected data content")
)

Functions

This section is empty.

Types

type Chunk

type Chunk struct {
	ID   [4]byte
	Size int
	R    io.Reader
	Pos  int
}

Chunk is a struct representing a data chunk the reader is shared with the container but convenience methods are provided. The reader always starts at the beggining of the data. SSND chunk is the sound chunk Chunk specs: http://www.onicos.com/staff/iz/formats/aiff.html AFAn seems to be an OS X specific chunk, meaning & format TBD

func (*Chunk) Done

func (ch *Chunk) Done()

Done makes sure the entire chunk was read.

func (*Chunk) IsFullyRead

func (ch *Chunk) IsFullyRead() bool

IsFullyRead checks if we're finished reading the chunk

func (*Chunk) Jump

func (ch *Chunk) Jump(bytesAhead int) error

Jump jumps ahead in the chunk

func (*Chunk) Read

func (ch *Chunk) Read(p []byte) (n int, err error)

Read implements the reader interface

func (*Chunk) ReadBE

func (ch *Chunk) ReadBE(dst interface{}) error

ReadBE reads the Big Endian chunk data into the passed struct

func (*Chunk) ReadByte

func (ch *Chunk) ReadByte() (byte, error)

ReadByte reads and returns a single byte

func (*Chunk) ReadLE

func (ch *Chunk) ReadLE(dst interface{}) error

ReadLE reads the Little Endian chunk data into the passed struct

type Decoder

type Decoder struct {

	// ID is always 'FORM'. This indicates that this is a FORM chunk
	ID [4]byte
	// Size contains the size of data portion of the 'FORM' chunk.
	// Note that the data portion has been
	// broken into two parts, formType and chunks
	Size uint32
	// Form describes what's in the 'FORM' chunk. For Audio IFF files,
	// formType (aka Format) is always 'AIFF'.
	// This indicates that the chunks within the FORM pertain to sampled sound.
	Form [4]byte

	NumChans        uint16
	NumSampleFrames uint32
	BitDepth        uint16
	SampleRate      int
	//
	PCMSize  uint32
	PCMChunk *Chunk

	// AIFC data
	Encoding     [4]byte
	EncodingName string

	Debug bool
	// contains filtered or unexported fields
}

Decoder is the wrapper structure for the AIFF container

func NewDecoder

func NewDecoder(r io.ReadSeeker) *Decoder

NewDecoder creates a new reader reading the given reader and pushing audio data to the given channel. It is the caller's responsibility to call Close on the reader when done.

func (*Decoder) Duration

func (d *Decoder) Duration() (time.Duration, error)

Duration returns the time duration for the current AIFF container

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/mattetti/audio/aiff"
)

func main() {
	path, _ := filepath.Abs("fixtures/kick.aif")
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	c := aiff.NewDecoder(f)
	d, _ := c.Duration()
	fmt.Printf("kick.aif has a duration of %f seconds\n", d.Seconds())
}
Output:

kick.aif has a duration of 0.203356 seconds

func (*Decoder) EOF

func (d *Decoder) EOF() bool

EOF returns positively if the underlying reader reached the end of file.

func (*Decoder) Err

func (d *Decoder) Err() error

Err returns the first non-EOF error that was encountered by the Decoder.

func (*Decoder) Format

func (d *Decoder) Format() *audio.Format

Format returns the audio format of the decoded content.

func (*Decoder) FullPCMBuffer

func (d *Decoder) FullPCMBuffer() (*audio.PCMBuffer, error)

FullPCMBuffer is an inneficient way to access all the PCM data contained in the audio container. The entire PCM data is held in memory. Consider using Buffer() instead.

func (*Decoder) FwdToPCM

func (d *Decoder) FwdToPCM() error

FwdToPCM forwards the underlying reader until the start of the PCM chunk. If the PCM chunk was already read, no data will be found (you need to rewind).

func (*Decoder) IsValidFile

func (d *Decoder) IsValidFile() bool

IsValidFile verifies that the file is valid/readable.

Example
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/mattetti/audio/aiff"
)

func main() {
	f, err := os.Open("fixtures/kick.aif")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	fmt.Printf("is this file valid: %t", aiff.NewDecoder(f).IsValidFile())
}
Output:

is this file valid: true

func (*Decoder) NextChunk

func (d *Decoder) NextChunk() (*Chunk, error)

NextChunk returns the next available chunk

func (*Decoder) PCMBuffer

func (d *Decoder) PCMBuffer(buf *audio.PCMBuffer) error

PCMBuffer populates the passed PCM buffer

func (*Decoder) PCMLen

func (d *Decoder) PCMLen() int64

PCMLen returns the total number of bytes in the PCM data chunk

func (*Decoder) ReadInfo

func (d *Decoder) ReadInfo()

ReadInfo reads the underlying reader until the comm header is parsed. This method is safe to call multiple times.

func (*Decoder) Reset

func (d *Decoder) Reset()

Reset resets the decoder (and rewind the underlying reader)

func (*Decoder) SampleBitDepth

func (d *Decoder) SampleBitDepth() int32

SampleBitDepth returns the bit depth encoding of each sample.

func (*Decoder) String

func (d *Decoder) String() string

String implements the Stringer interface.

func (*Decoder) WasPCMAccessed

func (d *Decoder) WasPCMAccessed() bool

WasPCMAccessed returns positively if the PCM data was previously accessed.

type Encoder

type Encoder struct {
	SampleRate int
	BitDepth   int
	NumChans   int

	WrittenBytes int
	// contains filtered or unexported fields
}

Encoder encodes LPCM data into an aiff content.

func NewEncoder

func NewEncoder(w io.WriteSeeker, sampleRate, bitDepth, numChans int) *Encoder

NewEncoder creates a new encoder to create a new aiff file. Don't forget to add Frames to the encoder before writing.

func (*Encoder) AddBE

func (e *Encoder) AddBE(src interface{}) error

AddBE serializes and adds the passed value using big endian

func (*Encoder) AddLE

func (e *Encoder) AddLE(src interface{}) error

AddLE serializes and adds the passed value using little endian

func (*Encoder) Close

func (e *Encoder) Close() error

Close flushes the content to disk, make sure the headers are up to date Note that the underlying writter is NOT being closed.

func (*Encoder) Write

func (e *Encoder) Write(buf *audio.PCMBuffer) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL