Documentation
¶
Overview ¶
Package wav is a package allowing developers to decode and encode audio PCM data using the Waveform Audio File Format https://en.wikipedia.org/wiki/WAV
Index ¶
- Variables
- func DecodeCueChunk(d *Decoder, ch *riff.Chunk) error
- func DecodeListChunk(d *Decoder, ch *riff.Chunk) error
- func DecodeSamplerChunk(d *Decoder, ch *riff.Chunk) error
- type CuePoint
- type Decoder
- func (d *Decoder) Duration() (time.Duration, error)
- func (d *Decoder) EOF() bool
- func (d *Decoder) Err() error
- func (d *Decoder) Format() *audio.Format
- func (d *Decoder) FullPCMBuffer() (*audio.IntBuffer, error)
- func (d *Decoder) FwdToPCM() error
- func (d *Decoder) IsValidFile() bool
- func (d *Decoder) NextChunk() (*riff.Chunk, error)
- func (d *Decoder) PCMBuffer(buf *audio.IntBuffer) (n int, err error)
- func (d *Decoder) PCMLen() int64
- func (d *Decoder) ReadInfo()
- func (d *Decoder) ReadMetadata()
- func (d *Decoder) Rewind() error
- func (d *Decoder) SampleBitDepth() int32
- func (d *Decoder) Seek(offset int64, whence int) (int64, error)
- func (d *Decoder) String() string
- func (d *Decoder) WasPCMAccessed() bool
- type Encoder
- func (e *Encoder) AddBE(src interface{}) error
- func (e *Encoder) AddLE(src interface{}) error
- func (e *Encoder) Close() error
- func (e *Encoder) Write(buf *audio.IntBuffer) error
- func (e *Encoder) WriteAt(buf *audio.IntBuffer, pos int64) (int64, error)
- func (e *Encoder) WriteFrame(value interface{}) error
- type Metadata
- type SampleLoop
- type SamplerInfo
- type WriterAtSeeker
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // CIDList is the chunk ID for a LIST chunk CIDList = [4]byte{'L', 'I', 'S', 'T'} // CIDSmpl is the chunk ID for a smpl chunk CIDSmpl = [4]byte{'s', 'm', 'p', 'l'} // CIDINFO is the chunk ID for an INFO chunk CIDInfo = []byte{'I', 'N', 'F', 'O'} // CIDCue is the chunk ID for the cue chunk CIDCue = [4]byte{'c', 'u', 'e', 0x20} )
var ( // ErrPCMChunkNotFound indicates a bad audio file without data ErrPCMChunkNotFound = errors.New("PCM Chunk not found in audio file") )
Functions ¶
func DecodeCueChunk ¶
DecodeCueChunk decodes the optional cue chunk and extracts cue points.
func DecodeListChunk ¶
DecodeListChunk decodes a LIST chunk
Types ¶
type CuePoint ¶
type CuePoint struct {
// ID is the unique identifier of the cue point
ID [4]byte
// Play position specifies the sample offset associated with the cue point
// in terms of the sample's position in the final stream of samples
// generated by the play list. If a play list chunk is
// specified, the position value is equal to the sample number at which this
// cue point will occur during playback of the entire play list as defined
// by the play list's order. If no play list chunk is specified this value
// should be 0.
Position uint32
// DataChunkID - This value specifies the four byte ID used by the chunk
// containing the sample that corresponds to this cue point. A Wave file
// with no play list is always "data". A Wave file with a play list
// containing both sample data and silence may be either "data" or "slnt".
DataChunkID [4]byte
// ChunkStart specifies the byte offset into the Wave List Chunk of the
// chunk containing the sample that corresponds to this cue point. This is
// the same chunk described by the Data Chunk ID value. If no Wave List
// Chunk exists in the Wave file, this value is 0. If a Wave List Chunk
// exists, this is the offset into the "wavl" chunk. The first chunk in the
// Wave List Chunk would be specified with a value of 0.
ChunkStart uint32
// BlockStart specifies the byte offset into the "data" or "slnt" Chunk to
// the start of the block containing the sample. The start of a block is
// defined as the first byte in uncompressed PCM wave data or the last byte
// in compressed wave data where decompression can begin to find the value
// of the corresponding sample value.
BlockStart uint32
// SampleOffset specifies an offset into the block (specified by Block
// Start) for the sample that corresponds to the cue point. In uncompressed
// PCM waveform data, this is simply the byte offset into the "data" chunk.
// In compressed waveform data, this value is equal to the number of samples
// (may or may not be bytes) from the Block Start to the sample that
// corresponds to the cue point.
SampleOffset uint32
}
CuePoint defines an offset which marks a noteworthy sections of the audio content. For example, the beginning and end of a verse in a song may have cue points to make them easier to find.
type Decoder ¶
type Decoder struct {
NumChans uint16
BitDepth uint16
SampleRate uint32
AvgBytesPerSec uint32
WavAudioFormat uint16
PCMSize int
// pcmChunk is available so we can use the LimitReader
PCMChunk *riff.Chunk
// Metadata for the current file
Metadata *Metadata
// contains filtered or unexported fields
}
Decoder handles the decoding of wav files.
func NewDecoder ¶
func NewDecoder(r io.ReadSeeker) *Decoder
NewDecoder creates a decoder for the passed wav reader. Note that the reader doesn't get rewinded as the container is processed.
func (*Decoder) Duration ¶
Duration returns the time duration for the current audio container
Example ¶
f, err := os.Open("fixtures/kick.wav")
if err != nil {
log.Fatal(err)
}
defer f.Close()
dur, err := NewDecoder(f).Duration()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s duration: %s\n", f.Name(), dur)
Output: fixtures/kick.wav duration: 204.172335ms
func (*Decoder) FullPCMBuffer ¶
FullPCMBuffer is an inefficient way to access all the PCM data contained in the audio container. The entire PCM data is held in memory. Consider using PCMBuffer() instead.
func (*Decoder) FwdToPCM ¶
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 ¶
IsValidFile verifies that the file is valid/readable.
Example ¶
f, err := os.Open("fixtures/kick.wav")
if err != nil {
log.Fatal(err)
}
defer f.Close()
fmt.Printf("is this file valid: %t", NewDecoder(f).IsValidFile())
Output: is this file valid: true
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) ReadMetadata ¶
func (d *Decoder) ReadMetadata()
ReadMetadata parses the file for extra metadata such as the INFO list chunk. The entire file will be read and should be rewinded if more data must be accessed.
Example ¶
f, err := os.Open("fixtures/listinfo.wav")
if err != nil {
log.Fatal(err)
}
defer f.Close()
d := NewDecoder(f)
d.ReadMetadata()
if d.Err() != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", d.Metadata)
Output: &wav.Metadata{SamplerInfo:(*wav.SamplerInfo)(nil), Artist:"artist", Comments:"my comment", Copyright:"", CreationDate:"2017", Engineer:"", Technician:"", Genre:"genre", Keywords:"", Medium:"", Title:"track title", Product:"album title", Subject:"", Software:"", Source:"", Location:"", TrackNbr:"42", CuePoints:[]*wav.CuePoint(nil)}
func (*Decoder) Rewind ¶
Rewind allows the decoder to be rewound to the beginning of the PCM data. This is useful if you want to keep on decoding the same file in a loop.
func (*Decoder) SampleBitDepth ¶
SampleBitDepth returns the bit depth encoding of each sample.
func (*Decoder) WasPCMAccessed ¶
WasPCMAccessed returns positively if the PCM data was previously accessed.
type Encoder ¶
type Encoder struct {
SampleRate int
BitDepth int
NumChans int
// A number indicating the WAVE format category of the file. The content of
// the <format-specific-fields> portion of the ‘fmt’ chunk, and the
// interpretation of the waveform data, depend on this value. PCM = 1 (i.e.
// Linear quantization) Values other than 1 indicate some form of
// compression.
WavAudioFormat int
// Metadata contains metadata to inject in the file.
Metadata *Metadata
WrittenBytes int
// contains filtered or unexported fields
}
Encoder encodes LPCM data into a wav containter.
func NewEncoder ¶
func NewEncoder(w WriterAtSeeker, sampleRate, bitDepth, numChans, audioFormat int) *Encoder
NewEncoder creates a new encoder to create a new wav file. Don't forget to add Frames to the encoder before writing.
func (*Encoder) Close ¶
Close flushes the content to disk, make sure the headers are up to date Note that the underlying writer is NOT being closed.
func (*Encoder) Write ¶
Write encodes and writes the passed buffer to the underlying writer. Don't forget to Close() the encoder or the file won't be valid.
Example ¶
f, err := os.Open("fixtures/kick.wav")
if err != nil {
panic(fmt.Sprintf("couldn't open audio file - %v", err))
}
// Decode the original audio file
// and collect audio content and information.
d := NewDecoder(f)
buf, err := d.FullPCMBuffer()
if err != nil {
panic(err)
}
f.Close()
fmt.Println("Old file ->", d)
// Destination file
out, err := os.Create("testOutput/kick.wav")
if err != nil {
panic(fmt.Sprintf("couldn't create output file - %v", err))
}
// setup the encoder and write all the frames
e := NewEncoder(out,
buf.Format.SampleRate,
int(d.BitDepth),
buf.Format.NumChannels,
int(d.WavAudioFormat))
if err = e.Write(buf); err != nil {
panic(err)
}
// close the encoder to make sure the headers are properly
// set and the data is flushed.
if err = e.Close(); err != nil {
panic(err)
}
out.Close()
// reopen to confirm things worked well
out, err = os.Open("testOutput/kick.wav")
if err != nil {
panic(err)
}
d2 := NewDecoder(out)
d2.ReadInfo()
fmt.Println("New file ->", d2)
out.Close()
os.Remove(out.Name())
Output: Old file -> Format: WAVE - 1 channels @ 22050 / 16 bits - Duration: 0.204172 seconds New file -> Format: WAVE - 1 channels @ 22050 / 16 bits - Duration: 0.204172 seconds
func (*Encoder) WriteFrame ¶
WriteFrame writes a single frame of data to the underlying writer.
type Metadata ¶
type Metadata struct {
SamplerInfo *SamplerInfo
// Artist of the original subject of the file. For example, Michaelangelo.
Artist string
// Comments provides general comments about the file or the subject of the
// file. If the comment is several sentences long, end each sentence with a
// period. Do not include newline characters.
Comments string
// Copyright records the copyright information for the file.
Copyright string
// CreationDate specifies the date the subject of the file was created. List
// dates in year-month-day format, padding one-digit months and days with a
// zero on the left. For example: 1553-05-03 for May 3, 1553. The year
// should always be given using four digits.
CreationDate string
// Engineer stores the name of the engineer who worked on the file. If there
// are multiple engineers, separate the names by a semicolon and a blank.
// For example: Smith, John; Adams, Joe.
Engineer string
// Technician identifies the technician who sampled the subject file. For
// example: Smith, John.
Technician string
// Genre describes the original work, such as jazz, classical, rock, etc.
Genre string
// Keywords provides a list of keywords that refer to the file or subject of
// the file. Separate multiple keywords with a semicolon and a blank. For
// example, Seattle; zoology; The Civil War.
Keywords string
// Medium describes the original subject of the file, such as record, CD and so forth.
Medium string
// Title stores the title of the subject of the file, such as bohemian rhapsody.
Title string
// Product AKA album specifies the name of the title the file was originally
// intended for: A Night at the Opera
Product string
// Subject describes the contents of the file, such as Metadata Management.
Subject string
// Software identifies the name of the software package used to create the
// file, such as go-audio.
Software string
// Source identifies the name of the person or organization who supplied the
// original subject of the file. For example: Splice.
Source string
// Location or Archival Location - Indicates where the subject of the file is archived.
Location string
// TrackNbr is the track number
TrackNbr string
// CuePoints is a list of cue points in the wav file.
CuePoints []*CuePoint
}
Metadata represents optional metadata added to the wav file.
type SampleLoop ¶
type SampleLoop struct {
// CuePointID - The Cue Point ID specifies the unique ID that corresponds to one of the
// defined cue points in the cue point list. Furthermore, this ID
// corresponds to any labels defined in the associated data list chunk which
// allows text labels to be assigned to the various sample loops.
CuePointID [4]byte
// Type - The type field defines how the waveform samples will be looped.
// 0 Loop forward (normal)
// 1 Alternating loop (forward/backward, also known as Ping Pong)
// 2 Loop backward (reverse)
// 3 Reserved for future standard types
// 32 - 0xFFFFFFFF Sampler specific types (defined by manufacturer)
Type uint32
// Start - The start value specifies the byte offset into the waveform data
// of the first sample to be played in the loop.
Start uint32
// End - The end value specifies the byte offset into the waveform data of
// the last sample to be played in the loop.
End uint32
// Fraction - The fractional value specifies a fraction of a sample at which
// to loop. This allows a loop to be fine tuned at a resolution greater than
// one sample. The value can range from 0x00000000 to 0xFFFFFFFF. A value of
// 0 means no fraction, a value of 0x80000000 means 1/2 of a sample length.
// 0xFFFFFFFF is the smallest fraction of a sample that can be represented.
Fraction uint32
// PlayCount - The play count value determines the number of times to play
// the loop. A value of 0 specifies an infinite sustain loop. An infinite
// sustain loop will continue looping until some external force interrupts
// playback, such as the musician releasing the key that triggered the
// wave's playback. All other values specify an absolute number of times to
// loop.
PlayCount uint32
}
SampleLoop indicates a loop and its properties within the audio file
type SamplerInfo ¶
type SamplerInfo struct {
// Manufacturer field specifies the MIDI Manufacturer's Association
// (MMA) Manufacturer code for the sampler intended to receive this file's
// waveform. Each manufacturer of a MIDI product is assigned a unique ID
// which identifies the company. If no particular manufacturer is to be
// specified, a value of 0 should be used. The value is stored with some
// extra information to enable translation to the value used in a MIDI
// System Exclusive transmission to the sampler. The high byte indicates the
// number of low order bytes (1 or 3) that are valid for the manufacturer
// code. For example, the value for Digidesign will be 0x01000013 (0x13) and
// the value for Microsoft will be 0x30000041 (0x00, 0x00, 0x41).
Manufacturer [4]byte
// Product field specifies the MIDI model ID defined by the manufacturer
// corresponding to the Manufacturer field. Contact the manufacturer of the
// sampler to get the model ID. If no particular manufacturer's product is
// to be specified, a value of 0 should be used.
Product [4]byte
// SamplePeriod The sample period specifies the duration of time that passes
// during the playback of one sample in nanoseconds (normally equal to 1 /
// Samplers Per Second, where Samples Per Second is the value found in the
// format chunk).
SamplePeriod uint32
// MIDIUnityNote The MIDI unity note value has the same meaning as the instrument chunk's
// MIDI Unshifted Note field which specifies the musical note at which the
// sample will be played at it's original sample rate (the sample rate
// specified in the format chunk).
MIDIUnityNote uint32
// MIDIPitchFraction The MIDI pitch fraction specifies the fraction of a
// semitone up from the specified MIDI unity note field. A value of
// 0x80000000 means 1/2 semitone (50 cents) and a value of 0x00000000 means
// no fine tuning between semitones.
MIDIPitchFraction uint32
// SMPTEFormat The SMPTE format specifies the Society of Motion Pictures and
// Television E time format used in the following SMPTE Offset field. If a
// value of 0 is set, SMPTE Offset should also be set to 0. (0, 24, 25, 29, 30)
SMPTEFormat uint32
// SMPTEOffset The SMPTE Offset value specifies the time offset to be used
// for the synchronization / calibration to the first sample in the
// waveform. This value uses a format of 0xhhmmssff where hh is a signed
// value that specifies the number of hours (-23 to 23), mm is an unsigned
// value that specifies the number of minutes (0 to 59), ss is an unsigned
// value that specifies the number of seconds (0 to 59) and ff is an
// unsigned value that specifies the number of frames (0 to -1).
SMPTEOffset uint32
// NumSampleLoops The sample loops field specifies the number Sample Loop
// definitions in the following list. This value may be set to 0 meaning
// that no sample loops follow.
NumSampleLoops uint32
// Loops A list of sample loops is simply a set of consecutive loop
// descriptions. The sample loops do not have to be in any particular order
// because each sample loop associated cue point position is used to
// determine the play order.
Loops []*SampleLoop
}
SamplerInfo is extra metadata pertinent to a sampler type usage.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gen-sine
command
|
|
|
metadata
command
This tool reads metadata from the passed wav file if available.
|
This tool reads metadata from the passed wav file if available. |
|
wavtagger
command
This command line tool helps the user tag wav files by injecting metadata in the file in a safe way.
|
This command line tool helps the user tag wav files by injecting metadata in the file in a safe way. |
|
wavtoaiff
command
This tool converts an aiff file into an identical wav file and stores it in the same folder as the source.
|
This tool converts an aiff file into an identical wav file and stores it in the same folder as the source. |