Skip to content

Commit

Permalink
set/get string test, raw offset test
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Kane committed Oct 3, 2011
1 parent b32873c commit 767245a
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 26 deletions.
5 changes: 4 additions & 1 deletion src/sndfile/.gitignore
Expand Up @@ -13,4 +13,7 @@ update
broadcast
scalefactor.aiff
test/funky2.aiff
musicenztrumentz.aiff
musicenztrumentz.aiff
rawtest
openfd
getsetstring.wav
2 changes: 1 addition & 1 deletion src/sndfile/Makefile
Expand Up @@ -15,6 +15,6 @@ CGOFILES=\
raw.go\
virtual.go

CLEANFILES+=leout.wav truncout.aiff addpeakchunk1.aiff norm.aiff funky2.aiff update broadcast musicenztrumentz.aiff
CLEANFILES+=leout.wav truncout.aiff addpeakchunk1.aiff norm.aiff funky2.aiff update broadcast musicenztrumentz.aiff rawtest openfd getsetstring.wav

include $(GOROOT)/src/Make.pkg
3 changes: 1 addition & 2 deletions src/sndfile/command.go
Expand Up @@ -249,8 +249,7 @@ func (f *File) genericBoolBoolCmd(cmd C.int, i bool) bool {
return (n == C.SF_TRUE)
}

//Change the data start offset for files opened up as SF_FORMAT_RAW.
// needstest
//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 os.Error) {
r := C.sf_command(f.s, C.SFC_SET_RAW_START_OFFSET, unsafe.Pointer(&count), 8)

Expand Down
39 changes: 39 additions & 0 deletions src/sndfile/command_test.go
Expand Up @@ -633,6 +633,45 @@ func TestInstrument(t *testing.T) {

}

// don't run this. looks like the actual command is a no-op!
func testRawOffset(t *testing.T) {
var i Info
i.Format = SF_FORMAT_RAW|SF_FORMAT_PCM_S8
i.Samplerate = 8000
i.Channels = 1

f, err := Open("rawtest", Write, &i)
if err != nil {
t.Fatal("Writing file failed", err)
}
for i := int16(-256); i <= 255; i++ {
f.WriteItems([]int16{i<<8})
}
/* n, err := f.WriteFrames([]int16{0x100, 0x200,0x300,0x400,0x500,0x600,0x700,0x7f00})
if err != nil || n != 4 {
t.Error("Writing file failed", err)
}*/
var n int64
f.Close()

f, err = Open("rawtest", Read, &i)
if err != nil {
t.Fatal("reading file failed", err)
}
err = f.SetRawStartOffset(4)
if err != nil {
t.Error("set raw start failed!",err)
}
buf := make([]int16,4)
n, err = f.ReadFrames(buf)
if err != nil || n != 4 {
t.Fatal("reading file failed", n, err)
}
if !reflect.DeepEqual(buf, []int16{0x500,0x600,0x700,0x800}) {
t.Error("bad stuff", buf, []int16{0x500,0x600,0x700,0x800})
}
}

// two left i can do without needing to find test data elsewhere:
// get/set ambisonic
// get set clipping
Expand Down
49 changes: 27 additions & 22 deletions src/sndfile/sndfile.go
Expand Up @@ -11,13 +11,16 @@ import (
"os"
"unsafe"
"reflect"
//"fmt"
)

// A sound file. Does not conform to io.Reader.
type File struct {
s *C.SNDFILE
Format Info
virtual *virtualIo // really only necessary to keep a reference so GC doesn't eat it
fd int
closeFd bool
}

// sErrorType represents a sndfile API error and grabs error description strings from the API.
Expand Down Expand Up @@ -167,15 +170,12 @@ func Open(name string, mode Mode, info *Info) (o *File, err os.Error) {
// This probably won't work on windows, because go uses handles instead of integer file descriptors on Windows. Unfortunately I have no way to test.
// The mode and info arguments, and the return values, are the same as for Open().
// close_desc should be true if you want the library to close the file descriptor when you close the sndfile.File object
// needs test.
func OpenFd(fd int, mode Mode, info *Info, close_desc bool) (o *File, err os.Error) {
o = new(File)
var cd C.int
if close_desc {
cd = 1
}
o.closeFd = close_desc
o.fd = fd
ci := info.toCinfo()
o.s = C.sf_open_fd(C.int(fd), C.int(mode), ci, cd)
o.s = C.sf_open_fd(C.int(fd), C.int(mode), ci, 0) // don't want libsndfile to close a Go file object from under us
if o.s == nil {
err = sErrorType(C.sf_error(o.s))
}
Expand Down Expand Up @@ -216,11 +216,15 @@ func (f *File) Close() (err os.Error) {
if C.sf_close(f.s) != 0 {
err = sErrorType(C.sf_error(f.s))
}
if f.closeFd {
nf := os.NewFile(f.fd, "")
nf.Close()
}

return
}

//If the file is opened Write or ReadWrite, call the operating system's function to force the writing of all file cache buffers to disk. If the file is opened Read no action is taken.
// needs test
func (f *File) WriteSync() {
C.sf_write_sync(f.s)
}
Expand All @@ -242,7 +246,7 @@ func (f *File) ReadItems(out interface{}) (read int64, err os.Error) {

v := reflect.ValueOf(out)
l := v.Len()
o := v.Slice(0, l-1)
o := v.Slice(0, l)
var n C.sf_count_t
switch t.Elem().Kind() {
case reflect.Int16:
Expand Down Expand Up @@ -288,7 +292,7 @@ func (f *File) ReadFrames(out interface{}) (read int64, err os.Error) {

v := reflect.ValueOf(out)
l := v.Len()
o := v.Slice(0, l-1)
o := v.Slice(0, l)
frames := l / int(f.Format.Channels)
if frames < 1 {
err = os.EOF
Expand Down Expand Up @@ -353,19 +357,16 @@ const (
)

//The GetString() method returns the specified string if it exists and a NULL pointer otherwise. In addition to the string ids above, First (== Title) and Last (always the same as the highest numbers string id) are also available to allow iteration over all the available string ids.
// needs test
func (f *File) GetString(typ StringType) (out *string) {
func (f *File) GetString(typ StringType) (out string) {
// although it's not clear from the docs, sf_get_string doesn't require you to free the string that is returned
s := C.sf_get_string(f.s, C.int(typ))
if s != nil {
out = new(string)
*out = C.GoString(s)
out = C.GoString(s)
}
return
}

//The SetString() method sets the string data ina file. It returns nil on success and non-nil on error.
// needs test
//The SetString() method sets the string data in a file. It returns nil on success and non-nil on error.
func (f *File) SetString(in string, typ StringType) (err os.Error) {
s := C.CString(in)
defer C.free(unsafe.Pointer(s))
Expand All @@ -375,21 +376,21 @@ func (f *File) SetString(in string, typ StringType) (err os.Error) {
return
}

//The file write items functions write the data in the array pointed to by ptr to the file. The items parameter must be an integer product of the number of channels or an error will occur.
//The file write items function writes the data in the array or slice in the input argument to the file. The length of the slice must be an integer product of the number of channels or an error will occur.
//
//It is important to note that the data type used by the calling program and the data format of the file do not need to be the same. For instance, it is possible to open a 16 bit PCM encoded WAV file and write the data from a []float32. The library seamlessly converts between the two formats on-the-fly.
//
//Returns the number of items written (which should be the same as the items parameter).
// needs test
//Returns the number of items written (which should be the same as the length of the input parameter). err will be nil, except in case of failure

func (f *File) WriteItems(in interface{}) (written int64, err os.Error) {
t := reflect.TypeOf(in)
if t.Kind() != reflect.Array && t.Kind() != reflect.Slice {
os.NewError("You need to give me an array!")
}

v := reflect.ValueOf(in)
l := v.Len()
o := v.Slice(0, l-1)
o := v.Slice(0, l)
var n C.sf_count_t
p := unsafe.Pointer(o.Index(0).Addr().Pointer())
switch t.Elem().Kind() {
Expand Down Expand Up @@ -431,7 +432,11 @@ func (f *File) WriteItems(in interface{}) (written int64, err os.Error) {
return
}

// needs test + doc
//The file write frames function writes the data in the array or slice pointed to by the input argument to the file. The items parameter must be an integer product of the number of channels or an error will occur.
//
//It is important to note that the data type used by the calling program and the data format of the file do not need to be the same. For instance, it is possible to open a 16 bit PCM encoded WAV file and write the data from a []float32. The library seamlessly converts between the two formats on-the-fly.
//
//Returns the number of frames written (which should be the same as the length of the input parameter divided by the number of channels). err wil be nil except in case of failure
func (f *File) WriteFrames(in interface{}) (written int64, err os.Error) {
t := reflect.TypeOf(in)
if t.Kind() != reflect.Array && t.Kind() != reflect.Slice {
Expand All @@ -440,7 +445,7 @@ func (f *File) WriteFrames(in interface{}) (written int64, err os.Error) {

v := reflect.ValueOf(in)
l := v.Len()
o := v.Slice(0, l-1)
o := v.Slice(0, l)
frames := l / int(f.Format.Channels)
if frames < 1 {
err = os.EOF
Expand Down
52 changes: 52 additions & 0 deletions src/sndfile/sndfile_test.go
Expand Up @@ -4,6 +4,7 @@ import (
// "fmt"
"reflect"
"testing"
"os"
)

func goldenInfo() (i Info) {
Expand Down Expand Up @@ -190,3 +191,54 @@ func TestReadIntFramesSeek(t *testing.T) {
}
return
}

// openfd
func TestOpenFd(t *testing.T) {
osf, err := os.Create("openfd")
if err != nil {
t.Fatal("err opening file for fd", err)
}
var i Info
i.Channels = 1
i.Samplerate = 44100
i.Format = SF_FORMAT_AIFF|SF_FORMAT_PCM_16
snf, err := OpenFd(osf.Fd(), Write, &i, true)
if err != nil {
t.Fatal("err opening fd", err)
}
n, err := snf.WriteItems([]int16{1,2,3,4,5})
if n != 5 || err != nil {
t.Error("bad write", n, err)
}
snf.Close()
nf := os.NewFile(osf.Fd(), "openfd")
_, err = nf.Write([]byte{1,2,3,4,5})
if err == nil {
t.Error("File must not have closed")
}
}

// set/get string
func TestGetSetString(t *testing.T) {
s := "TEST_STRING_HOOAH"
var i Info
i.Format = SF_FORMAT_WAV|SF_FORMAT_PCM_16
i.Channels = 1
i.Samplerate = 44100
f, err := Open("getsetstring.wav", Write, &i)
if err != nil {
t.Fatal("couldn't open file to write", err)
}
f.SetString(s, First)
f.WriteItems([]int16{1,2,3,4,5})
f.Close()

f, err = Open("getsetstring.wav", Read, &i)
if err != nil {
t.Fatal("couldn't open file to read", err)
}
si := f.GetString(First)
if si != s {
t.Error("wrong string came back!", s, "!=", si)
}
}
Binary file modified src/sndfile/test/funky.aiff
Binary file not shown.

0 comments on commit 767245a

Please sign in to comment.