pcm, audio: style changes

This commit is contained in:
Trek H 2019-06-17 13:29:01 +09:30
parent 01561e363d
commit fb12a2f69e
2 changed files with 25 additions and 38 deletions

View File

@ -41,15 +41,14 @@ import (
// - If the number of bytes in b.Data is not divisible by the decimation factor (ratioFrom), the remaining bytes will
// not be included in the result. Eg. input of length 480002 downsampling 6:1 will result in output length 80000.
func Resample(b alsa.Buffer, rate int) (alsa.Buffer, error) {
var newBuf alsa.Buffer
if b.Format.Rate == rate {
return newBuf, nil
return b, nil
}
if b.Format.Rate < 0 {
return newBuf, fmt.Errorf("Unable to convert from: %v Hz", b.Format.Rate)
return alsa.Buffer{}, fmt.Errorf("Unable to convert from: %v Hz", b.Format.Rate)
}
if rate < 0 {
return newBuf, fmt.Errorf("Unable to convert to: %v Hz", rate)
return alsa.Buffer{}, fmt.Errorf("Unable to convert to: %v Hz", rate)
}
// The number of bytes in a sample.
@ -60,7 +59,7 @@ func Resample(b alsa.Buffer, rate int) (alsa.Buffer, error) {
case alsa.S16_LE:
sampleLen = 2 * b.Format.Channels
default:
return newBuf, fmt.Errorf("Unhandled ALSA format: %v", b.Format.SampleFormat)
return alsa.Buffer{}, fmt.Errorf("Unhandled ALSA format: %v", b.Format.SampleFormat)
}
inPcmLen := len(b.Data)
@ -71,7 +70,7 @@ func Resample(b alsa.Buffer, rate int) (alsa.Buffer, error) {
// ratioTo = 1 is the only number that will result in an even sampling.
if ratioTo != 1 {
return newBuf, fmt.Errorf("unhandled from:to rate ratio %v:%v: 'to' must be 1", ratioFrom, ratioTo)
return alsa.Buffer{}, fmt.Errorf("unhandled from:to rate ratio %v:%v: 'to' must be 1", ratioFrom, ratioTo)
}
newLen := inPcmLen / ratioFrom
@ -100,28 +99,25 @@ func Resample(b alsa.Buffer, rate int) (alsa.Buffer, error) {
resampled = append(resampled, bAvg...)
}
// Create new alsa.Buffer with resampled data.
newBuf = alsa.Buffer{
// Return a new alsa.Buffer with resampled data.
return alsa.Buffer{
Format: alsa.BufferFormat{
Channels: b.Format.Channels,
SampleFormat: b.Format.SampleFormat,
Rate: rate,
},
Data: resampled,
}
return newBuf, nil
}, nil
}
// StereoToMono returns raw mono audio data generated from only the left channel from
// the given stereo recording (ALSA buffer)
func StereoToMono(b alsa.Buffer) (alsa.Buffer, error) {
var newBuf alsa.Buffer
if b.Format.Channels == 1 {
return b, nil
}
if b.Format.Channels != 2 {
return newBuf, fmt.Errorf("Audio is not stereo or mono, it has %v channels", b.Format.Channels)
return alsa.Buffer{}, fmt.Errorf("Audio is not stereo or mono, it has %v channels", b.Format.Channels)
}
var stereoSampleBytes int
@ -131,7 +127,7 @@ func StereoToMono(b alsa.Buffer) (alsa.Buffer, error) {
case alsa.S16_LE:
stereoSampleBytes = 4
default:
return newBuf, fmt.Errorf("Unhandled ALSA format %v", b.Format.SampleFormat)
return alsa.Buffer{}, fmt.Errorf("Unhandled ALSA format %v", b.Format.SampleFormat)
}
recLength := len(b.Data)
@ -147,17 +143,15 @@ func StereoToMono(b alsa.Buffer) (alsa.Buffer, error) {
}
}
// Create new alsa.Buffer with resampled data.
newBuf = alsa.Buffer{
// Return a new alsa.Buffer with resampled data.
return alsa.Buffer{
Format: alsa.BufferFormat{
Channels: 1,
SampleFormat: b.Format.SampleFormat,
Rate: b.Format.Rate,
},
Data: mono,
}
return newBuf, nil
}, nil
}
// gcd is used for calculating the greatest common divisor of two positive integers, a and b.

View File

@ -43,13 +43,16 @@ import (
)
const (
pkg = "pkg: "
pkg = "audio: "
rbTimeout = 100 * time.Millisecond
rbNextTimeout = 100 * time.Millisecond
rbLen = 200
defaultSampleRate = 48000
)
// "running" means the input goroutine is reading from the ALSA device and writing to the ringbuffer.
// "paused" means the input routine is sleeping until unpaused or stopped.
// "stopped" means the input routine is stopped and the ALSA device is closed.
const (
running = iota
paused
@ -59,24 +62,17 @@ const (
// Rates contains the standard audio sample rates used by package audio.
var Rates = [8]int{8000, 16000, 32000, 44100, 48000, 88200, 96000, 192000}
// Device holds everything we need to know about the audio input stream.
// Device holds everything we need to know about the audio input stream and implements io.Reader.
type Device struct {
l Logger
// Operating mode, either running, paused, or stopped.
// "running" means the input goroutine is reading from the ALSA device and writing to the ringbuffer.
// "paused" means the input routine is sleeping until unpaused or stopped.
// "stopped" means the input routine is stopped and the ALSA device is closed.
mode uint8
mu sync.Mutex
l Logger // Logger for device's routines to log to.
mode uint8 // Operating mode, either running, paused, or stopped.
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
title string // Name of audio title, or empty for the default title.
dev *alsa.Device // Audio input device.
dev *alsa.Device // ALSA's Audio input device.
ab alsa.Buffer // ALSA's buffer.
rb *ring.Buffer // Our buffer.
chunkSize int // This is the number of bytes that will be stored at a time.
*Config
chunkSize int // This is the number of bytes that will be stored in rb at a time.
*Config // Configuration parameters for this device.
}
// Config provides parameters used by Device.
@ -155,7 +151,7 @@ func (d *Device) Start() error {
case running:
return nil
default:
return errors.New("invalid mode")
return fmt.Errorf("invalid mode: %d", mode)
}
}
@ -185,7 +181,6 @@ func (d *Device) open() error {
d.l.Log(logger.Debug, pkg+"opening sound card")
cards, err := alsa.OpenCards()
if err != nil {
d.l.Log(logger.Debug, pkg+"failed to open sound card")
return err
}
defer alsa.CloseCards(cards)
@ -207,14 +202,12 @@ func (d *Device) open() error {
}
}
if d.dev == nil {
d.l.Log(logger.Debug, pkg+"failed to find audio device")
return errors.New("no audio device found")
}
d.l.Log(logger.Debug, pkg+"opening audio device", "title", d.dev.Title)
err = d.dev.Open()
if err != nil {
d.l.Log(logger.Debug, pkg+"failed to open audio device")
return err
}