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) 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 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 ¶
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) 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 forger 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. |