pcm: changed term clip to buffer

This commit is contained in:
Trek H 2019-11-13 16:54:41 +10:30
parent 3a7c2c5c5e
commit 796a3b9a97
6 changed files with 68 additions and 68 deletions

View File

@ -79,7 +79,7 @@ type audioClient struct {
// internals
dev *yalsa.Device // audio input device
clip pcm.Clip // Clip to contain the recording.
buf pcm.Buffer // Buffer to contain the recording.
rb *ring.Buffer // our buffer
ns *netsender.Sender // our NetSender
vs int // our "var sum" to track var changes
@ -141,17 +141,17 @@ func main() {
if err != nil {
log.Log(logger.Error, err.Error())
}
cf := pcm.ClipFormat{
cf := pcm.BufferFormat{
SFormat: sf,
Channels: ab.Format.Channels,
Rate: ab.Format.Rate,
}
ac.clip = pcm.Clip{
ac.buf = pcm.Buffer{
Format: cf,
Data: ab.Data,
}
recSize := (((len(ac.clip.Data) / ac.dev.BufferFormat().Channels) * ac.channels) / ac.dev.BufferFormat().Rate) * ac.rate
recSize := (((len(ac.buf.Data) / ac.dev.BufferFormat().Channels) * ac.channels) / ac.dev.BufferFormat().Rate) * ac.rate
rbLen := rbDuration / ac.period
ac.rb = ring.NewBuffer(rbLen, recSize, rbTimeout)
@ -332,7 +332,7 @@ func (ac *audioClient) open() error {
// Re-opens the device and tries again if ASLA returns an error.
// Spends a lot of time sleeping in Paused mode.
// ToDo: Currently, reading audio and writing to the ringbuffer are synchronous.
// Need a way to asynchronously read from the clip, i.e., _while_ it is recording to avoid any gaps.
// Need a way to asynchronously read from the buf, i.e., _while_ it is recording to avoid any gaps.
func (ac *audioClient) input() {
for {
ac.mu.Lock()
@ -344,7 +344,7 @@ func (ac *audioClient) input() {
}
log.Log(logger.Debug, "recording audio for period", "seconds", ac.period)
ac.mu.Lock()
err := ac.dev.Read(ac.clip.Data)
err := ac.dev.Read(ac.buf.Data)
ac.mu.Unlock()
if err != nil {
log.Log(logger.Debug, "device.Read failed", "error", err.Error())
@ -386,7 +386,7 @@ func (ac *audioClient) input() {
// This function also handles NetReceiver configuration requests and updating of NetReceiver vars.
func (ac *audioClient) output() {
// Calculate the size of the output data based on wanted channels and rate.
outLen := (((len(ac.clip.Data) / ac.clip.Format.Channels) * ac.channels) / ac.clip.Format.Rate) * ac.rate
outLen := (((len(ac.buf.Data) / ac.buf.Format.Channels) * ac.channels) / ac.buf.Format.Rate) * ac.rate
buf := make([]byte, outLen)
mime := "audio/x-wav;codec=pcm;rate=" + strconv.Itoa(ac.rate) + ";channels=" + strconv.Itoa(ac.channels) + ";bits=" + strconv.Itoa(ac.bits)
@ -523,9 +523,9 @@ func read(rb *ring.Buffer, buf []byte) (int, error) {
return n, nil
}
// formatBuffer returns a Clip that has the recording data from the ac's original Clip but stored
// formatBuffer returns a Buffer that has the recording data from the ac's original Buffer but stored
// in the desired format specified by the ac's parameters.
func (ac *audioClient) formatBuffer() pcm.Clip {
func (ac *audioClient) formatBuffer() pcm.Buffer {
var err error
ac.mu.Lock()
wantChannels := ac.channels
@ -533,17 +533,17 @@ func (ac *audioClient) formatBuffer() pcm.Clip {
ac.mu.Unlock()
// If nothing needs to be changed, return the original.
if ac.clip.Format.Channels == wantChannels && ac.clip.Format.Rate == wantRate {
return ac.clip
if ac.buf.Format.Channels == wantChannels && ac.buf.Format.Rate == wantRate {
return ac.buf
}
formatted := pcm.Clip{Format: ac.clip.Format}
formatted := pcm.Buffer{Format: ac.buf.Format}
bufCopied := false
if ac.clip.Format.Channels != wantChannels {
if ac.buf.Format.Channels != wantChannels {
// Convert channels.
if ac.clip.Format.Channels == 2 && wantChannels == 1 {
if formatted, err = pcm.StereoToMono(ac.clip); err != nil {
if ac.buf.Format.Channels == 2 && wantChannels == 1 {
if formatted, err = pcm.StereoToMono(ac.buf); err != nil {
log.Log(logger.Warning, "channel conversion failed, audio has remained stereo", "error", err.Error())
} else {
formatted.Format.Channels = 1
@ -552,13 +552,13 @@ func (ac *audioClient) formatBuffer() pcm.Clip {
}
}
if ac.clip.Format.Rate != wantRate {
if ac.buf.Format.Rate != wantRate {
// Convert rate.
if bufCopied {
formatted, err = pcm.Resample(formatted, wantRate)
} else {
formatted, err = pcm.Resample(ac.clip, wantRate)
formatted, err = pcm.Resample(ac.buf, wantRate)
}
if err != nil {
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())

View File

@ -35,7 +35,7 @@ import (
"github.com/pkg/errors"
)
// SampleFormat is the format that a PCM Clip's samples can be in.
// SampleFormat is the format that a PCM Buffer's samples can be in.
type SampleFormat int
// Used to represent an unknown format.
@ -52,33 +52,33 @@ const (
// https://trac.ffmpeg.org/wiki/audio%20types
)
// ClipFormat contains the format for a PCM Clip.
type ClipFormat struct {
// BufferFormat contains the format for a PCM Buffer.
type BufferFormat struct {
SFormat SampleFormat
Rate int
Channels int
}
// Clip contains a clip of PCM data and the format that it is in.
type Clip struct {
Format ClipFormat
// Buffer contains a buffer of PCM data and the format that it is in.
type Buffer struct {
Format BufferFormat
Data []byte
}
// Resample takes Clip c and resamples the pcm audio data to 'rate' Hz and returns a Clip with the resampled data.
// Resample takes Buffer c and resamples the pcm audio data to 'rate' Hz and returns a Buffer with the resampled data.
// Notes:
// - Currently only downsampling is implemented and c's rate must be divisible by 'rate' or an error will occur.
// - If the number of bytes in c.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(c Clip, rate int) (Clip, error) {
func Resample(c Buffer, rate int) (Buffer, error) {
if c.Format.Rate == rate {
return c, nil
}
if c.Format.Rate < 0 {
return Clip{}, fmt.Errorf("Unable to convert from: %v Hz", c.Format.Rate)
return Buffer{}, fmt.Errorf("Unable to convert from: %v Hz", c.Format.Rate)
}
if rate < 0 {
return Clip{}, fmt.Errorf("Unable to convert to: %v Hz", rate)
return Buffer{}, fmt.Errorf("Unable to convert to: %v Hz", rate)
}
// The number of bytes in a sample.
@ -89,7 +89,7 @@ func Resample(c Clip, rate int) (Clip, error) {
case S16_LE:
sampleLen = 2 * c.Format.Channels
default:
return Clip{}, fmt.Errorf("Unhandled ALSA format: %v", c.Format.SFormat)
return Buffer{}, fmt.Errorf("Unhandled ALSA format: %v", c.Format.SFormat)
}
inPcmLen := len(c.Data)
@ -100,7 +100,7 @@ func Resample(c Clip, rate int) (Clip, error) {
// ratioTo = 1 is the only number that will result in an even sampling.
if ratioTo != 1 {
return Clip{}, fmt.Errorf("unhandled from:to rate ratio %v:%v: 'to' must be 1", ratioFrom, ratioTo)
return Buffer{}, fmt.Errorf("unhandled from:to rate ratio %v:%v: 'to' must be 1", ratioFrom, ratioTo)
}
newLen := inPcmLen / ratioFrom
@ -129,9 +129,9 @@ func Resample(c Clip, rate int) (Clip, error) {
resampled = append(resampled, bAvg...)
}
// Return a new Clip with resampled data.
return Clip{
Format: ClipFormat{
// Return a new Buffer with resampled data.
return Buffer{
Format: BufferFormat{
Channels: c.Format.Channels,
SFormat: c.Format.SFormat,
Rate: rate,
@ -141,13 +141,13 @@ func Resample(c Clip, rate int) (Clip, error) {
}
// StereoToMono returns raw mono audio data generated from only the left channel from
// the given stereo Clip
func StereoToMono(c Clip) (Clip, error) {
// the given stereo Buffer
func StereoToMono(c Buffer) (Buffer, error) {
if c.Format.Channels == 1 {
return c, nil
}
if c.Format.Channels != 2 {
return Clip{}, fmt.Errorf("Audio is not stereo or mono, it has %v channels", c.Format.Channels)
return Buffer{}, fmt.Errorf("Audio is not stereo or mono, it has %v channels", c.Format.Channels)
}
var stereoSampleBytes int
@ -157,7 +157,7 @@ func StereoToMono(c Clip) (Clip, error) {
case S16_LE:
stereoSampleBytes = 4
default:
return Clip{}, fmt.Errorf("Unhandled sample format %v", c.Format.SFormat)
return Buffer{}, fmt.Errorf("Unhandled sample format %v", c.Format.SFormat)
}
recLength := len(c.Data)
@ -173,9 +173,9 @@ func StereoToMono(c Clip) (Clip, error) {
}
}
// Return a new Clip with resampled data.
return Clip{
Format: ClipFormat{
// Return a new Buffer with resampled data.
return Buffer{
Format: BufferFormat{
Channels: 1,
SFormat: c.Format.SFormat,
Rate: c.Format.Rate,

View File

@ -45,19 +45,19 @@ func TestResample(t *testing.T) {
log.Fatal(err)
}
format := ClipFormat{
format := BufferFormat{
Channels: 1,
Rate: 48000,
SFormat: S16_LE,
}
clip := Clip{
buf := Buffer{
Format: format,
Data: inPcm,
}
// Resample pcm.
resampled, err := Resample(clip, 8000)
resampled, err := Resample(buf, 8000)
if err != nil {
log.Fatal(err)
}
@ -86,19 +86,19 @@ func TestStereoToMono(t *testing.T) {
log.Fatal(err)
}
format := ClipFormat{
format := BufferFormat{
Channels: 2,
Rate: 44100,
SFormat: S16_LE,
}
clip := Clip{
buf := Buffer{
Format: format,
Data: inPcm,
}
// Convert audio.
mono, err := StereoToMono(clip)
mono, err := StereoToMono(buf)
if err != nil {
log.Fatal(err)
}

View File

@ -68,7 +68,7 @@ type ALSA struct {
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
title string // Name of audio title, or empty for the default title.
dev *yalsa.Device // ALSA device's Audio input device.
clip pcm.Clip // Clip to contain the recording.
buf pcm.Buffer // Buffer to contain the recording.
rb *ring.Buffer // Our buffer.
chunkSize int // This is the number of bytes that will be stored in rb at a time.
Config // Configuration parameters for this device.
@ -139,18 +139,18 @@ func (d *ALSA) Set(c config.Config) error {
d.l.Log(logger.Error, pkg+err.Error())
return err
}
cf := pcm.ClipFormat{
cf := pcm.BufferFormat{
SFormat: sf,
Channels: ab.Format.Channels,
Rate: ab.Format.Rate,
}
d.clip = pcm.Clip{
d.buf = pcm.Buffer{
Format: cf,
Data: ab.Data,
}
// Account for channel conversion.
chunkSize := float64(len(d.clip.Data) / d.dev.BufferFormat().Channels * d.Channels)
chunkSize := float64(len(d.buf.Data) / d.dev.BufferFormat().Channels * d.Channels)
// Account for resampling.
chunkSize = (chunkSize / float64(d.dev.BufferFormat().Rate)) * float64(d.SampleRate)
@ -386,7 +386,7 @@ func (d *ALSA) input() {
// Read from audio device.
d.l.Log(logger.Debug, pkg+"recording audio for period", "seconds", d.RecPeriod)
err := d.dev.Read(d.clip.Data)
err := d.dev.Read(d.buf.Data)
if err != nil {
d.l.Log(logger.Debug, pkg+"read failed", "error", err.Error())
err = d.open() // re-open
@ -428,26 +428,26 @@ func (d *ALSA) Read(p []byte) (int, error) {
}
// formatBuffer returns audio that has been converted to the desired format.
func (d *ALSA) formatBuffer() pcm.Clip {
func (d *ALSA) formatBuffer() pcm.Buffer {
var err error
// If nothing needs to be changed, return the original.
if d.clip.Format.Channels == d.Channels && d.clip.Format.Rate == d.SampleRate {
return d.clip
if d.buf.Format.Channels == d.Channels && d.buf.Format.Rate == d.SampleRate {
return d.buf
}
var formatted pcm.Clip
if d.clip.Format.Channels != d.Channels {
var formatted pcm.Buffer
if d.buf.Format.Channels != d.Channels {
// Convert channels.
// TODO(Trek): Make this work for conversions other than stereo to mono.
if d.clip.Format.Channels == 2 && d.Channels == 1 {
formatted, err = pcm.StereoToMono(d.clip)
if d.buf.Format.Channels == 2 && d.Channels == 1 {
formatted, err = pcm.StereoToMono(d.buf)
if err != nil {
d.l.Log(logger.Fatal, pkg+"channel conversion failed", "error", err.Error())
}
}
}
if d.clip.Format.Rate != d.SampleRate {
if d.buf.Format.Rate != d.SampleRate {
// Convert rate.
formatted, err = pcm.Resample(formatted, d.SampleRate)
if err != nil {

View File

@ -62,19 +62,19 @@ func main() {
log.Fatalf("Unhandled ALSA format: %v", SFString)
}
format := pcm.ClipFormat{
format := pcm.BufferFormat{
Channels: channels,
Rate: from,
SFormat: sf,
}
clip := pcm.Clip{
buf := pcm.Buffer{
Format: format,
Data: inPcm,
}
// Resample audio.
resampled, err := pcm.Resample(clip, to)
resampled, err := pcm.Resample(buf, to)
if err != nil {
log.Fatal(err)
}

View File

@ -59,18 +59,18 @@ func main() {
log.Fatalf("Unhandled sample format: %v", SFString)
}
format := pcm.ClipFormat{
format := pcm.BufferFormat{
Channels: 2,
SFormat: sf,
}
clip := pcm.Clip{
buf := pcm.Buffer{
Format: format,
Data: inPcm,
}
// Convert audio.
mono, err := pcm.StereoToMono(clip)
mono, err := pcm.StereoToMono(buf)
if err != nil {
log.Fatal(err)
}