wavtest2.go (3035B)
1 package main 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 "os" 9 ) 10 11 // Thanks: https://wavefilegem.com/how_wave_files_work.html 12 type Wave struct { 13 ChunkID [4]byte 14 ChunkSize uint32 15 Format [4]byte 16 Subchunk1ID [4]byte 17 Subchunk1Size uint32 18 AudioFormat uint16 19 NumChannels uint16 20 SampleRate uint32 21 ByteRate uint32 22 BlockAlign uint16 23 BitsPerSample uint16 24 Subchunk2ID [4]byte 25 Subchunk2Size uint32 26 Data []byte 27 } 28 29 func (wav *Wave) Len() uint32 { 30 return uint32(len(wav.Data)) / uint32(wav.NumChannels*wav.BitsPerSample/8) 31 } 32 33 func (wav *Wave) LoadMetaData(file *os.File) { 34 // can use nil instead of BigEndian when reading into []byte (endianness is ignored) 35 binary.Read(file, binary.BigEndian, &wav.ChunkID) 36 binary.Read(file, binary.LittleEndian, &wav.ChunkSize) 37 binary.Read(file, binary.BigEndian, &wav.Format) 38 binary.Read(file, binary.BigEndian, &wav.Subchunk1ID) 39 binary.Read(file, binary.LittleEndian, &wav.Subchunk1Size) 40 binary.Read(file, binary.LittleEndian, &wav.AudioFormat) 41 binary.Read(file, binary.LittleEndian, &wav.NumChannels) 42 binary.Read(file, binary.LittleEndian, &wav.SampleRate) 43 binary.Read(file, binary.LittleEndian, &wav.ByteRate) 44 binary.Read(file, binary.LittleEndian, &wav.BlockAlign) 45 binary.Read(file, binary.LittleEndian, &wav.BitsPerSample) 46 binary.Read(file, binary.BigEndian, &wav.Subchunk2ID) 47 binary.Read(file, binary.LittleEndian, &wav.Subchunk2Size) 48 } 49 50 func LoadFile(filename string) *Wave { 51 file, err := os.Open(filename) 52 if err != nil { 53 fmt.Println("error when opening file:", err) 54 panic(err) 55 } 56 wav := Wave{} 57 wav.LoadMetaData(file) 58 wav.Data = make([]byte, wav.Subchunk2Size) 59 err = binary.Read(file, nil, &wav.Data) 60 if err != nil && err != io.EOF { 61 fmt.Println("error when reading wave data:", err) 62 } 63 return &wav 64 } 65 66 // PCM Int 16 and 32 are always signed integers 67 func (wav *Wave) FromInt32() [][]float64 { 68 fData := make([][]float64, wav.Len()) 69 buf := bytes.NewReader(wav.Data) 70 var err error 71 for n := uint32(0); n < wav.Len(); n++ { 72 fData[n] = make([]float64, wav.NumChannels) 73 var sample int32 74 for c := range fData[n] { 75 err = binary.Read(buf, binary.LittleEndian, &sample) 76 if err != nil { 77 panic(err) 78 } 79 fData[n][c] = float64(sample) / float64(1<<31) 80 } 81 } 82 return fData 83 } 84 85 func (wav *Wave) FromInt16() [][]float64 { 86 fData := make([][]float64, wav.Len()) 87 buf := bytes.NewReader(wav.Data) 88 var err error 89 for n := uint32(0); n < wav.Len(); n++ { 90 fData[n] = make([]float64, wav.NumChannels) 91 var sample int16 92 for c := range fData[n] { 93 err = binary.Read(buf, binary.LittleEndian, &sample) 94 if err != nil { 95 panic(err) 96 } 97 fData[n][c] = float64(sample) / float64(1<<15) 98 } 99 } 100 return fData 101 } 102 103 func main() { 104 if len(os.Args) < 2 { 105 fmt.Println("No filename given") 106 os.Exit(1) 107 } 108 wav := LoadFile(os.Args[1]) 109 switch wav.BitsPerSample { 110 case 16: 111 fmt.Println(wav.FromInt16()) 112 case 32: 113 fmt.Println(wav.FromInt32()) 114 default: 115 panic("unsupported number of bits per sample") 116 } 117 }