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
- type Metadata
- type SampleLoop
- type SamplerInfo
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 ¶ added in v1.1.0
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 io.WriteSeeker, 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
|
|
metadata
This tool reads metadata from the passed wav file if available.
|
This tool reads metadata from the passed wav file if available. |
wavtagger
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
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. |