func (rsc *Mp3ReaderSeekerCloser) Format() (rate int64, channels int, encoding int, format Format) { c_rate := (*C.long)(unsafe.Pointer(&rate)) c_channels := (*C.int)(unsafe.Pointer(&channels)) c_encoding := (*C.int)(unsafe.Pointer(&encoding)) C.mpg123_getformat(rsc.handle, c_rate, c_channels, c_encoding) if channels == 1 { if encoding&C.MPG123_ENC_8 != 0 { format = Mono8 } else if encoding&C.MPG123_ENC_16 != 0 { format = Mono16 } } else if channels == 2 { if encoding&C.MPG123_ENC_8 != 0 { format = Stereo8 } else if encoding&C.MPG123_ENC_16 != 0 { format = Stereo16 } } return }
func DecodeTrack(file string, control chan int) { var v1 *C.mpg123_id3v1 var v2 *C.mpg123_id3v2 m := C.mpg123_new(nil, nil) defer C.mpg123_delete(m) f := C.CString(file) if err := C.mpg123_open(m, f); err != C.MPG123_OK { panic("Error reading file") } defer C.mpg123_close(m) C.mpg123_scan(m) meta := C.mpg123_meta_check(m) if meta == C.MPG123_ID3 && C.mpg123_id3(m, &v1, &v2) == C.MPG123_OK { var title, artist, album, genre string switch false { case v2 == nil: fmt.Println("ID3V2 tag found") title = C.GoString(v2.title.p) artist = C.GoString(v2.artist.p) album = C.GoString(v2.album.p) genre = C.GoString(v2.genre.p) case v1 == nil: fmt.Println("ID3V2 tag found") title = C.GoString(&v1.title[0]) artist = C.GoString(&v1.artist[0]) album = C.GoString(&v1.album[0]) genre = "Unknown" // FIXME convert int to string } fmt.Println(title) fmt.Println(artist) fmt.Println(album) fmt.Println(genre) } default_driver := C.ao_default_driver_id() var format C.ao_sample_format var device *C.ao_device var channels, encoding C.int var rate C.long C.mpg123_getformat(m, &rate, &channels, &encoding) format.bits = 16 format.channels = channels format.rate = C.int(rate) format.byte_format = C.AO_FMT_LITTLE device = C.ao_open_live(default_driver, &format, nil) if device == nil { panic("Error opening device") return } defer C.ao_close(device) var ret C.int var fill C.size_t buf := make([]C.uchar, 1024*16) for { ret = C.mpg123_read(m, (*C.uchar)(unsafe.Pointer(&buf)), 16*1024, &fill) if ret == C.MPG123_DONE { control <- 1 break } C.ao_play(device, (*C.char)(unsafe.Pointer(&buf)), 16*1024) } }
// Returns current output format func (d *Decoder) GetFormat() (rate int64, channels int, encoding int) { var cRate C.long var cChans, cEnc C.int C.mpg123_getformat(d.handle, &cRate, &cChans, &cEnc) return int64(cRate), int(cChans), int(cEnc) }
func (d *Decoder) Read(p []byte) (n int, err error) { d.mu.Lock() defer d.mu.Unlock() if d.closed { return 0, io.EOF } var stat C.int loop: for { var rn int rn, err = d.src.Read(d.buf) if err != nil && err != io.EOF { return n, err } var cn C.size_t stat = C.mpg123_decode(d.mh, (*C.uchar)(unsafe.Pointer(&d.buf[0])), C.size_t(rn), (*C.uchar)(unsafe.Pointer(&p[n])), C.size_t(len(p)-n), &cn, ) n += int(cn) switch stat { case C.MPG123_NEED_MORE: // mpg123 is asking for more data, so loop around if // we haven't reached EOF in the reader yet. if err == io.EOF { // We've exhausted the io.Reader and cleaned all // the internal buffers of mpg123, so we can signal // a proper EOF to our caller. return n, io.EOF } // Otherwise we just want more data break case C.MPG123_NEW_FORMAT: // mpg123 is notifying us of a new format coming up var rate C.long var chans, enc C.int err := toError(C.mpg123_getformat(d.mh, &rate, &chans, &enc)) if err != nil { log.Println("error while getting stream format:", err) } fallthrough default: break loop } } // Check for read error from the src if err != nil && err != io.EOF { return n, err } if stat != C.MPG123_OK && stat != C.MPG123_NEW_FORMAT { return n, toError(stat) } return n, nil }