// Retrieve the log buffer generated when opening a file as a string. This log buffer can often contain a good reason for why libsndfile failed to open a particular file. func (f *File) GetLogInfo() (s string, err error) { l := C.sf_command(f.s, C.SFC_GET_LOG_INFO, nil, 0) c := make([]byte, l) m := C.sf_command(f.s, C.SFC_GET_LOG_INFO, unsafe.Pointer(&c[0]), l) if m != l { c = c[0:m] } s = string(c) return }
// GetLibVersion retrieves the version of the library as a string func GetLibVersion() (s string, err error) { l := C.sf_command(nil, C.SFC_GET_LIB_VERSION, nil, 0) c := make([]byte, l) m := C.sf_command(nil, C.SFC_GET_LIB_VERSION, unsafe.Pointer(&c[0]), l) if m != l { err = errors.New(fmt.Sprintf("GetLibVersion: expected %d bytes in string, recv'd %d", l, m)) } s = string(c) return }
//Retrieve the peak value for the file as stored in the file header. func (f *File) GetSignalMax() (ret float64, ok bool) { r := C.sf_command(f.s, C.SFC_GET_SIGNAL_MAX, unsafe.Pointer(&ret), 8) if r == C.SF_TRUE { ok = true } return }
// Retrieve the measured normalised maximum signal value. This involves reading through the whole file which can be slow on large files. func (f *File) CalcNormSignalMax() (ret float64, err error) { e := C.sf_command(f.s, C.SFC_CALC_NORM_SIGNAL_MAX, unsafe.Pointer(&ret), 8) if e != 0 { err = sErrorType(e) } return }
// Return true if the file header contains instrument information for the file. false otherwise. func (f *File) SetInstrument(i *Instrument) bool { c := new(C.SF_INSTRUMENT) c.gain = C.int(i.Gain) c.basenote = C.char(i.Basenote) c.detune = C.char(i.Detune) c.velocity_lo = C.char(i.Velocity[0]) c.velocity_hi = C.char(i.Velocity[1]) c.key_lo = C.char(i.Key[0]) c.key_hi = C.char(i.Key[1]) c.loop_count = C.int(i.LoopCount) var index int for ; index < i.LoopCount; index++ { c.loops[index].mode = C.int(i.Loops[index].Mode) c.loops[index].start = C.uint32_t(i.Loops[index].Start) c.loops[index].end = C.uint32_t(i.Loops[index].End) c.loops[index].count = C.uint32_t(i.Loops[index].Count) } for ; index < 16; index++ { c.loops[index].mode = C.int(None) // why is this necessary? libsndfile doesn't check loopcount for AIFF } r := C.sf_command(f.s, C.SFC_SET_INSTRUMENT, unsafe.Pointer(c), C.int(unsafe.Sizeof(*c))) return (r == C.SF_TRUE) }
// This allows libsndfile experts to use the command interface for commands not currently supported. See http://www.mega-nerd.com/libsndfile/command.html // The f argument may be nil in cases where the command does not require a SNDFILE argument. // The method's cmd, data, and datasize arguments are used the same way as the correspondingly named arguments for sf_command func GenericCmd(f *File, cmd C.int, data unsafe.Pointer, datasize int) int { var s *C.SNDFILE = nil if f != nil { s = f.s } return int(C.sf_command(s, cmd, data, C.int(datasize))) }
//Set the the Variable Bit Rate encoding quality. The encoding quality value should be between 0.0 (lowest quality) and 1.0 (highest quality). Untested. func (f *File) SetVbrQuality(q float64) (err error) { r := C.sf_command(f.s, C.SFC_SET_VBR_ENCODING_QUALITY, unsafe.Pointer(&q), 8) if r != 0 { err = errors.New(C.GoString(C.sf_strerror(f.s))) } return }
// Set the Broadcast Extension Chunk from WAV (and related) files. func (f *File) SetBroadcastInfo(bi *BroadcastInfo) (err error) { c := cFromBroadcast(bi) r := C.sf_command(f.s, C.SFC_SET_BROADCAST_INFO, unsafe.Pointer(c), C.int(unsafe.Sizeof(*c))) if r == C.SF_FALSE { err = errors.New(C.GoString(C.sf_strerror(f.s))) } return }
//Change the data start offset for files opened up as SF_FORMAT_RAW. libsndfile implements this but it appears to not do anything useful that you can't accomplish with seek, so consider this deprecated. func (f *File) SetRawStartOffset(count int64) (err error) { r := C.sf_command(f.s, C.SFC_SET_RAW_START_OFFSET, unsafe.Pointer(&count), 8) if r != 0 { err = errors.New(C.GoString(C.sf_strerror(f.s))) } return }
// Truncates a file to /count/ frames. After this command, both the read and the write pointer will be at the new end of the file. This command will fail (returning non-zero) if the requested truncate position is beyond the end of the file. func (f *File) Truncate(count int64) (err error) { r := C.sf_command(f.s, C.SFC_FILE_TRUNCATE, unsafe.Pointer(&count), 8) if r != 0 { err = errors.New(C.GoString(C.sf_strerror(f.s))) } return }
//Enumerate the subtypes (this function does not translate a subtype into a string describing that subtype). A typical use case might be retrieving a string description of all subtypes so that a dialog box can be filled in. func GetSubFormatInfo(format int) (oformat int, name string, ok bool) { var o C.SF_FORMAT_INFO o.format = C.int(format) ok = (0 == C.sf_command(nil, C.SFC_GET_FORMAT_SUBTYPE, unsafe.Pointer(&o), C.int(unsafe.Sizeof(o)))) oformat = int(o.format) name = C.GoString(o.name) return }
func (f *File) genericBoolBoolCmd(cmd C.int, i bool) bool { ib := C.SF_FALSE if i { ib = C.SF_TRUE } n := C.sf_command(f.s, cmd, nil, C.int(ib)) return (n == C.SF_TRUE) }
//Retrieve information about a major format type //For a more comprehensive example, see the program list_formats.c in the examples/ directory of the libsndfile source code distribution. func GetMajorFormatInfo(format int) (oformat int, name string, extension string, ok bool) { var o C.SF_FORMAT_INFO o.format = C.int(format) ok = (0 == C.sf_command(nil, C.SFC_GET_FORMAT_MAJOR, unsafe.Pointer(&o), C.int(unsafe.Sizeof(o)))) oformat = int(o.format) name = C.GoString(o.name) extension = C.GoString(o.extension) return }
//Calculate the normalised peak for each channel. This involves reading through the whole file which can be slow on large files. func (f *File) CalcNormMaxAllChannels() (ret []float64, err error) { c := f.Format.Channels ret = make([]float64, c) e := C.sf_command(f.s, C.SFC_CALC_NORM_MAX_ALL_CHANNELS, unsafe.Pointer(&ret[0]), C.int(c*8)) if e != 0 { err = sErrorType(e) } return }
//Retrieve the peak value for the file as stored in the file header. func (f *File) GetMaxAllChannels() (ret []float64, ok bool) { c := f.Format.Channels ret = make([]float64, c) e := C.sf_command(f.s, C.SFC_GET_MAX_ALL_CHANNELS, unsafe.Pointer(&ret[0]), C.int(c*8)) if e == C.SF_TRUE { ok = true } return }
//Get the file offset and file length of a file enbedded within another larger file. //The value of the offset return value will be the offsets in bytes from the start of the outer file to the start of the embedded audio file. //The value of the length return value will be the length in bytes of the embedded file. // Untested. func (f *File) GetEmbeddedFileInfo() (offset, length int64, err error) { var s C.SF_EMBED_FILE_INFO r := C.sf_command(f.s, C.SFC_GET_EMBED_FILE_INFO, unsafe.Pointer(&s), C.int(unsafe.Sizeof(s))) if r != 0 { err = errors.New(C.GoString(C.sf_strerror(f.s))) } offset = int64(s.offset) length = int64(s.length) return }
// Retrieve the Broadcast Extension Chunk from WAV (and related) files. func (f *File) GetBroadcastInfo() (bi *BroadcastInfo, ok bool) { bic := new(C.SF_BROADCAST_INFO) r := C.sf_command(f.s, C.SFC_GET_BROADCAST_INFO, unsafe.Pointer(bic), C.int(unsafe.Sizeof(*bic))) if r == C.SF_TRUE { bi = broadcastFromC(bic) ok = true } return }
// Returns populated structure if file contains loop info, otherwise nil. Untested. func (f *File) GetLoopInfo() (i *LoopInfo) { c := new(C.SF_LOOP_INFO) r := C.sf_command(f.s, C.SFC_GET_LOOP_INFO, unsafe.Pointer(c), C.int(unsafe.Sizeof(*c))) if r == C.SF_TRUE { i = new(LoopInfo) i.TimeSig.Numerator = int16(c.time_sig_num) i.TimeSig.Denominator = int16(c.time_sig_den) i.Mode = LoopMode(c.loop_mode) i.Beats = int(c.num_beats) i.Bpm = float32(c.bpm) i.RootKey = int(c.root_key) for index, value := range c.future { i.Future[index] = int(value) } } return }
// Return pointer to populated structure if the file header contains instrument information for the file. nil otherwise. func (f *File) GetInstrument() (i *Instrument) { c := new(C.SF_INSTRUMENT) i = new(Instrument) r := C.sf_command(f.s, C.SFC_GET_INSTRUMENT, unsafe.Pointer(c), C.int(unsafe.Sizeof(*c))) if r == C.SF_TRUE { i.Gain = int(c.gain) i.Basenote = int8(c.basenote) i.Detune = int8(c.detune) i.Velocity[0] = int8(c.velocity_lo) i.Velocity[1] = int8(c.velocity_hi) i.Key[0] = int8(c.key_lo) i.Key[1] = int8(c.key_hi) i.LoopCount = int(c.loop_count) for index, loop := range c.loops { i.Loops[index].Mode = LoopMode(loop.mode) i.Loops[index].Start = uint(loop.start) i.Loops[index].End = uint(loop.end) i.Loops[index].Count = uint(loop.count) } } return }
//Retrieve the number of major formats supported by libsndfile. func GetMajorFormatCount() int { var o C.int C.sf_command(nil, C.SFC_GET_FORMAT_MAJOR_COUNT, unsafe.Pointer(&o), C.int(unsafe.Sizeof(o))) return int(o) }
//Retrieve the number of subformats supported by libsndfile. func GetSubFormatCount() int { var o C.int C.sf_command(nil, C.SFC_GET_FORMAT_SUBTYPE_COUNT, unsafe.Pointer(&o), C.int(unsafe.Sizeof(o))) return int(o) }
//There are however situations where large files are being generated and it would be nice to have valid data in the header before the file is complete. Using this command will update the file header to reflect the amount of data written to the file so far. Other programs opening the file for read (before any more data is written) will then read a valid sound file header. func (f *File) UpdateHeaderNow() { C.sf_command(f.s, C.SFC_UPDATE_HEADER_NOW, nil, 0) }
//Set the GUID of a new WAVEX file to indicate an Ambisonics format. // returns format that was just set, or zero if the file format does not support Ambisonic formats func (f *File) WavexSetAmbisonic(ambi int) int { return int(C.sf_command(f.s, C.SFC_WAVEX_SET_AMBISONIC, nil, C.int(ambi))) }
//Test if the current file has the GUID of a WAVEX file for any of the Ambisonic formats. // returns AmbisonicNone or AmbisonicBFormat, or zero if the file format does not support Ambisonic formats func (f *File) WavexGetAmbisonic() int { return int(C.sf_command(f.s, C.SFC_WAVEX_GET_AMBISONIC, nil, 0)) }
//Retrieve the number of simple formats supported by libsndfile. func GetSimpleFormatCount() int { var o C.int C.sf_command(nil, C.SFC_GET_SIMPLE_FORMAT_COUNT, unsafe.Pointer(&o), C.int(unsafe.Sizeof(o))) return int(o) }