| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // +build !wasm
- package audio
- import (
- "fmt"
- "github.com/g3n/engine/audio/al"
- "os"
- )
- // WaveSpecs describes the characteristics of the audio encoded in a wave file.
- type WaveSpecs struct {
- Format int // OpenAl Format
- Type int // Type field from wave header
- Channels int // Number of channels
- SampleRate int // Sample rate in hz
- BitsSample int // Number of bits per sample (8 or 16)
- DataSize int // Total data size in bytes
- BytesSec int // Bytes per second
- TotalTime float64 // Total time in seconds
- }
- const (
- waveHeaderSize = 44
- fileMark = "RIFF"
- fileHead = "WAVE"
- )
- // WaveCheck checks if the specified filepath corresponds to a an audio wave file.
- // If the file is a valid wave file, return a pointer to WaveSpec structure
- // with information about the encoded audio data.
- func WaveCheck(filepath string) (*WaveSpecs, error) {
- // Open file
- f, err := os.Open(filepath)
- if err != nil {
- return nil, err
- }
- defer f.Close()
- // Reads header
- header := make([]uint8, waveHeaderSize)
- n, err := f.Read(header)
- if err != nil {
- return nil, err
- }
- if n < waveHeaderSize {
- return nil, fmt.Errorf("File size less than header")
- }
- // Checks file marks
- if string(header[0:4]) != fileMark {
- return nil, fmt.Errorf("'RIFF' mark not found")
- }
- if string(header[8:12]) != fileHead {
- return nil, fmt.Errorf("'WAVE' mark not found")
- }
- // Decodes header fields
- var ws WaveSpecs
- ws.Format = -1
- ws.Type = int(header[20]) + int(header[21])<<8
- ws.Channels = int(header[22]) + int(header[23])<<8
- ws.SampleRate = int(header[24]) + int(header[25])<<8 + int(header[26])<<16 + int(header[27])<<24
- ws.BitsSample = int(header[34]) + int(header[35])<<8
- ws.DataSize = int(header[40]) + int(header[41])<<8 + int(header[42])<<16 + int(header[43])<<24
- // Sets OpenAL format field if possible
- if ws.Channels == 1 {
- if ws.BitsSample == 8 {
- ws.Format = al.FormatMono8
- } else if ws.BitsSample == 16 {
- ws.Format = al.FormatMono16
- }
- } else if ws.Channels == 2 {
- if ws.BitsSample == 8 {
- ws.Format = al.FormatStereo8
- } else if ws.BitsSample == 16 {
- ws.Format = al.FormatStereo16
- }
- }
- // Calculates bytes/sec and total time
- var bytesChannel int
- if ws.BitsSample == 8 {
- bytesChannel = 1
- } else {
- bytesChannel = 2
- }
- ws.BytesSec = ws.SampleRate * ws.Channels * bytesChannel
- ws.TotalTime = float64(ws.DataSize) / float64(ws.BytesSec)
- return &ws, nil
- }
|