mirror of https://bitbucket.org/ausocean/av.git
pcm: changed term clip to buffer
This commit is contained in:
parent
3a7c2c5c5e
commit
796a3b9a97
|
@ -79,7 +79,7 @@ type audioClient struct {
|
||||||
|
|
||||||
// internals
|
// internals
|
||||||
dev *yalsa.Device // audio input device
|
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
|
rb *ring.Buffer // our buffer
|
||||||
ns *netsender.Sender // our NetSender
|
ns *netsender.Sender // our NetSender
|
||||||
vs int // our "var sum" to track var changes
|
vs int // our "var sum" to track var changes
|
||||||
|
@ -141,17 +141,17 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Error, err.Error())
|
log.Log(logger.Error, err.Error())
|
||||||
}
|
}
|
||||||
cf := pcm.ClipFormat{
|
cf := pcm.BufferFormat{
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
Channels: ab.Format.Channels,
|
Channels: ab.Format.Channels,
|
||||||
Rate: ab.Format.Rate,
|
Rate: ab.Format.Rate,
|
||||||
}
|
}
|
||||||
ac.clip = pcm.Clip{
|
ac.buf = pcm.Buffer{
|
||||||
Format: cf,
|
Format: cf,
|
||||||
Data: ab.Data,
|
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
|
rbLen := rbDuration / ac.period
|
||||||
ac.rb = ring.NewBuffer(rbLen, recSize, rbTimeout)
|
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.
|
// Re-opens the device and tries again if ASLA returns an error.
|
||||||
// Spends a lot of time sleeping in Paused mode.
|
// Spends a lot of time sleeping in Paused mode.
|
||||||
// ToDo: Currently, reading audio and writing to the ringbuffer are synchronous.
|
// 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() {
|
func (ac *audioClient) input() {
|
||||||
for {
|
for {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
|
@ -344,7 +344,7 @@ func (ac *audioClient) input() {
|
||||||
}
|
}
|
||||||
log.Log(logger.Debug, "recording audio for period", "seconds", ac.period)
|
log.Log(logger.Debug, "recording audio for period", "seconds", ac.period)
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
err := ac.dev.Read(ac.clip.Data)
|
err := ac.dev.Read(ac.buf.Data)
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Debug, "device.Read failed", "error", err.Error())
|
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.
|
// This function also handles NetReceiver configuration requests and updating of NetReceiver vars.
|
||||||
func (ac *audioClient) output() {
|
func (ac *audioClient) output() {
|
||||||
// Calculate the size of the output data based on wanted channels and rate.
|
// 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)
|
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)
|
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
|
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.
|
// 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
|
var err error
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
wantChannels := ac.channels
|
wantChannels := ac.channels
|
||||||
|
@ -533,17 +533,17 @@ func (ac *audioClient) formatBuffer() pcm.Clip {
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
|
|
||||||
// If nothing needs to be changed, return the original.
|
// If nothing needs to be changed, return the original.
|
||||||
if ac.clip.Format.Channels == wantChannels && ac.clip.Format.Rate == wantRate {
|
if ac.buf.Format.Channels == wantChannels && ac.buf.Format.Rate == wantRate {
|
||||||
return ac.clip
|
return ac.buf
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted := pcm.Clip{Format: ac.clip.Format}
|
formatted := pcm.Buffer{Format: ac.buf.Format}
|
||||||
bufCopied := false
|
bufCopied := false
|
||||||
if ac.clip.Format.Channels != wantChannels {
|
if ac.buf.Format.Channels != wantChannels {
|
||||||
|
|
||||||
// Convert channels.
|
// Convert channels.
|
||||||
if ac.clip.Format.Channels == 2 && wantChannels == 1 {
|
if ac.buf.Format.Channels == 2 && wantChannels == 1 {
|
||||||
if formatted, err = pcm.StereoToMono(ac.clip); err != nil {
|
if formatted, err = pcm.StereoToMono(ac.buf); err != nil {
|
||||||
log.Log(logger.Warning, "channel conversion failed, audio has remained stereo", "error", err.Error())
|
log.Log(logger.Warning, "channel conversion failed, audio has remained stereo", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
formatted.Format.Channels = 1
|
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.
|
// Convert rate.
|
||||||
if bufCopied {
|
if bufCopied {
|
||||||
formatted, err = pcm.Resample(formatted, wantRate)
|
formatted, err = pcm.Resample(formatted, wantRate)
|
||||||
} else {
|
} else {
|
||||||
formatted, err = pcm.Resample(ac.clip, wantRate)
|
formatted, err = pcm.Resample(ac.buf, wantRate)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())
|
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())
|
||||||
|
|
|
@ -35,7 +35,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"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
|
type SampleFormat int
|
||||||
|
|
||||||
// Used to represent an unknown format.
|
// Used to represent an unknown format.
|
||||||
|
@ -52,33 +52,33 @@ const (
|
||||||
// https://trac.ffmpeg.org/wiki/audio%20types
|
// https://trac.ffmpeg.org/wiki/audio%20types
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClipFormat contains the format for a PCM Clip.
|
// BufferFormat contains the format for a PCM Buffer.
|
||||||
type ClipFormat struct {
|
type BufferFormat struct {
|
||||||
SFormat SampleFormat
|
SFormat SampleFormat
|
||||||
Rate int
|
Rate int
|
||||||
Channels int
|
Channels int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clip contains a clip of PCM data and the format that it is in.
|
// Buffer contains a buffer of PCM data and the format that it is in.
|
||||||
type Clip struct {
|
type Buffer struct {
|
||||||
Format ClipFormat
|
Format BufferFormat
|
||||||
Data []byte
|
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:
|
// Notes:
|
||||||
// - Currently only downsampling is implemented and c's rate must be divisible by 'rate' or an error will occur.
|
// - 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
|
// - 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.
|
// 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 {
|
if c.Format.Rate == rate {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
if c.Format.Rate < 0 {
|
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 {
|
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.
|
// The number of bytes in a sample.
|
||||||
|
@ -89,7 +89,7 @@ func Resample(c Clip, rate int) (Clip, error) {
|
||||||
case S16_LE:
|
case S16_LE:
|
||||||
sampleLen = 2 * c.Format.Channels
|
sampleLen = 2 * c.Format.Channels
|
||||||
default:
|
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)
|
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.
|
// ratioTo = 1 is the only number that will result in an even sampling.
|
||||||
if ratioTo != 1 {
|
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
|
newLen := inPcmLen / ratioFrom
|
||||||
|
@ -129,9 +129,9 @@ func Resample(c Clip, rate int) (Clip, error) {
|
||||||
resampled = append(resampled, bAvg...)
|
resampled = append(resampled, bAvg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a new Clip with resampled data.
|
// Return a new Buffer with resampled data.
|
||||||
return Clip{
|
return Buffer{
|
||||||
Format: ClipFormat{
|
Format: BufferFormat{
|
||||||
Channels: c.Format.Channels,
|
Channels: c.Format.Channels,
|
||||||
SFormat: c.Format.SFormat,
|
SFormat: c.Format.SFormat,
|
||||||
Rate: rate,
|
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
|
// StereoToMono returns raw mono audio data generated from only the left channel from
|
||||||
// the given stereo Clip
|
// the given stereo Buffer
|
||||||
func StereoToMono(c Clip) (Clip, error) {
|
func StereoToMono(c Buffer) (Buffer, error) {
|
||||||
if c.Format.Channels == 1 {
|
if c.Format.Channels == 1 {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
if c.Format.Channels != 2 {
|
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
|
var stereoSampleBytes int
|
||||||
|
@ -157,7 +157,7 @@ func StereoToMono(c Clip) (Clip, error) {
|
||||||
case S16_LE:
|
case S16_LE:
|
||||||
stereoSampleBytes = 4
|
stereoSampleBytes = 4
|
||||||
default:
|
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)
|
recLength := len(c.Data)
|
||||||
|
@ -173,9 +173,9 @@ func StereoToMono(c Clip) (Clip, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a new Clip with resampled data.
|
// Return a new Buffer with resampled data.
|
||||||
return Clip{
|
return Buffer{
|
||||||
Format: ClipFormat{
|
Format: BufferFormat{
|
||||||
Channels: 1,
|
Channels: 1,
|
||||||
SFormat: c.Format.SFormat,
|
SFormat: c.Format.SFormat,
|
||||||
Rate: c.Format.Rate,
|
Rate: c.Format.Rate,
|
||||||
|
|
|
@ -45,19 +45,19 @@ func TestResample(t *testing.T) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
format := ClipFormat{
|
format := BufferFormat{
|
||||||
Channels: 1,
|
Channels: 1,
|
||||||
Rate: 48000,
|
Rate: 48000,
|
||||||
SFormat: S16_LE,
|
SFormat: S16_LE,
|
||||||
}
|
}
|
||||||
|
|
||||||
clip := Clip{
|
buf := Buffer{
|
||||||
Format: format,
|
Format: format,
|
||||||
Data: inPcm,
|
Data: inPcm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resample pcm.
|
// Resample pcm.
|
||||||
resampled, err := Resample(clip, 8000)
|
resampled, err := Resample(buf, 8000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -86,19 +86,19 @@ func TestStereoToMono(t *testing.T) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
format := ClipFormat{
|
format := BufferFormat{
|
||||||
Channels: 2,
|
Channels: 2,
|
||||||
Rate: 44100,
|
Rate: 44100,
|
||||||
SFormat: S16_LE,
|
SFormat: S16_LE,
|
||||||
}
|
}
|
||||||
|
|
||||||
clip := Clip{
|
buf := Buffer{
|
||||||
Format: format,
|
Format: format,
|
||||||
Data: inPcm,
|
Data: inPcm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert audio.
|
// Convert audio.
|
||||||
mono, err := StereoToMono(clip)
|
mono, err := StereoToMono(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ type ALSA struct {
|
||||||
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
|
mu sync.Mutex // Provides synchronisation when changing modes concurrently.
|
||||||
title string // Name of audio title, or empty for the default title.
|
title string // Name of audio title, or empty for the default title.
|
||||||
dev *yalsa.Device // ALSA device's Audio input device.
|
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.
|
rb *ring.Buffer // Our buffer.
|
||||||
chunkSize int // This is the number of bytes that will be stored in rb at a time.
|
chunkSize int // This is the number of bytes that will be stored in rb at a time.
|
||||||
Config // Configuration parameters for this device.
|
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())
|
d.l.Log(logger.Error, pkg+err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cf := pcm.ClipFormat{
|
cf := pcm.BufferFormat{
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
Channels: ab.Format.Channels,
|
Channels: ab.Format.Channels,
|
||||||
Rate: ab.Format.Rate,
|
Rate: ab.Format.Rate,
|
||||||
}
|
}
|
||||||
d.clip = pcm.Clip{
|
d.buf = pcm.Buffer{
|
||||||
Format: cf,
|
Format: cf,
|
||||||
Data: ab.Data,
|
Data: ab.Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for channel conversion.
|
// 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.
|
// Account for resampling.
|
||||||
chunkSize = (chunkSize / float64(d.dev.BufferFormat().Rate)) * float64(d.SampleRate)
|
chunkSize = (chunkSize / float64(d.dev.BufferFormat().Rate)) * float64(d.SampleRate)
|
||||||
|
@ -386,7 +386,7 @@ func (d *ALSA) input() {
|
||||||
|
|
||||||
// Read from audio device.
|
// Read from audio device.
|
||||||
d.l.Log(logger.Debug, pkg+"recording audio for period", "seconds", d.RecPeriod)
|
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 {
|
if err != nil {
|
||||||
d.l.Log(logger.Debug, pkg+"read failed", "error", err.Error())
|
d.l.Log(logger.Debug, pkg+"read failed", "error", err.Error())
|
||||||
err = d.open() // re-open
|
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.
|
// 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
|
var err error
|
||||||
|
|
||||||
// If nothing needs to be changed, return the original.
|
// If nothing needs to be changed, return the original.
|
||||||
if d.clip.Format.Channels == d.Channels && d.clip.Format.Rate == d.SampleRate {
|
if d.buf.Format.Channels == d.Channels && d.buf.Format.Rate == d.SampleRate {
|
||||||
return d.clip
|
return d.buf
|
||||||
}
|
}
|
||||||
var formatted pcm.Clip
|
var formatted pcm.Buffer
|
||||||
if d.clip.Format.Channels != d.Channels {
|
if d.buf.Format.Channels != d.Channels {
|
||||||
// Convert channels.
|
// Convert channels.
|
||||||
// TODO(Trek): Make this work for conversions other than stereo to mono.
|
// TODO(Trek): Make this work for conversions other than stereo to mono.
|
||||||
if d.clip.Format.Channels == 2 && d.Channels == 1 {
|
if d.buf.Format.Channels == 2 && d.Channels == 1 {
|
||||||
formatted, err = pcm.StereoToMono(d.clip)
|
formatted, err = pcm.StereoToMono(d.buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.l.Log(logger.Fatal, pkg+"channel conversion failed", "error", err.Error())
|
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.
|
// Convert rate.
|
||||||
formatted, err = pcm.Resample(formatted, d.SampleRate)
|
formatted, err = pcm.Resample(formatted, d.SampleRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -62,19 +62,19 @@ func main() {
|
||||||
log.Fatalf("Unhandled ALSA format: %v", SFString)
|
log.Fatalf("Unhandled ALSA format: %v", SFString)
|
||||||
}
|
}
|
||||||
|
|
||||||
format := pcm.ClipFormat{
|
format := pcm.BufferFormat{
|
||||||
Channels: channels,
|
Channels: channels,
|
||||||
Rate: from,
|
Rate: from,
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
}
|
}
|
||||||
|
|
||||||
clip := pcm.Clip{
|
buf := pcm.Buffer{
|
||||||
Format: format,
|
Format: format,
|
||||||
Data: inPcm,
|
Data: inPcm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resample audio.
|
// Resample audio.
|
||||||
resampled, err := pcm.Resample(clip, to)
|
resampled, err := pcm.Resample(buf, to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,18 +59,18 @@ func main() {
|
||||||
log.Fatalf("Unhandled sample format: %v", SFString)
|
log.Fatalf("Unhandled sample format: %v", SFString)
|
||||||
}
|
}
|
||||||
|
|
||||||
format := pcm.ClipFormat{
|
format := pcm.BufferFormat{
|
||||||
Channels: 2,
|
Channels: 2,
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
}
|
}
|
||||||
|
|
||||||
clip := pcm.Clip{
|
buf := pcm.Buffer{
|
||||||
Format: format,
|
Format: format,
|
||||||
Data: inPcm,
|
Data: inPcm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert audio.
|
// Convert audio.
|
||||||
mono, err := pcm.StereoToMono(clip)
|
mono, err := pcm.StereoToMono(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue