mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2025-04-02 11:02:17 -04:00
television signal split into video and audio signal. The audio signal is only sent then a new sample from the TIA is ready realtime mixer concept change. the mixer can be informed of a change of TV spec. this allows the realtime mixer to make an informed judgement about the required sample rate the sample rate is unlikely to be ideal however unless the number of scanlines in the TV image is the same as given in the basic TV specification (ie. 262 lines for NTSC, 312 for PAL). because of that, the realtime mixer can also indirectly regulate the rate of calls to SetAudio(). the Regulate() function is called by the television which then alters the call frequency to SetAudio() depending on the regulate value. this effectively keeps the audio buffer nicely filled - neither too long which would be audibly laggy, or too short which would result in clipped audio the values that control the regulation in both the sdlaudio package and television package will need tweaking to find the best values
96 lines
2.5 KiB
Go
96 lines
2.5 KiB
Go
// This file is part of Gopher2600.
|
|
//
|
|
// Gopher2600 is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Gopher2600 is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
// Package wavwriter allows writing of audio data to disk as a WAV file.
|
|
package wavwriter
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/jetsetilly/gopher2600/hardware/television/signal"
|
|
tia "github.com/jetsetilly/gopher2600/hardware/tia/audio"
|
|
"github.com/jetsetilly/gopher2600/hardware/tia/audio/mix"
|
|
|
|
"github.com/go-audio/audio"
|
|
"github.com/go-audio/wav"
|
|
)
|
|
|
|
// WavWriter implements the television.AudioMixer interface
|
|
type WavWriter struct {
|
|
filename string
|
|
buffer []int16
|
|
}
|
|
|
|
// New is the preferred method of initialisation for the WavWriter type
|
|
func NewWavWriter(filename string) (*WavWriter, error) {
|
|
aw := &WavWriter{
|
|
filename: fmt.Sprintf("%s.wav", filename),
|
|
buffer: make([]int16, 0, 0),
|
|
}
|
|
return aw, nil
|
|
}
|
|
|
|
// SetAudio implements the television.AudioMixer interface.
|
|
func (aw *WavWriter) SetAudio(sig []signal.AudioSignalAttributes) error {
|
|
for _, s := range sig {
|
|
v0 := s.AudioChannel0
|
|
v1 := s.AudioChannel1
|
|
|
|
m := mix.Mono(v0, v1)
|
|
aw.buffer = append(aw.buffer, m)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
const numChannels = 1
|
|
const bitDepth = 16
|
|
|
|
// EndMixing implements the television.AudioMixer interface
|
|
func (aw *WavWriter) EndMixing() error {
|
|
f, err := os.Create(aw.filename)
|
|
if err != nil {
|
|
return fmt.Errorf("wavwriter: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
enc := wav.NewEncoder(f, tia.AverageSampleFreq, bitDepth, numChannels, 1)
|
|
if enc == nil {
|
|
return fmt.Errorf("wavwriter: bad parameters for wav encoding")
|
|
}
|
|
defer enc.Close()
|
|
|
|
buf := audio.PCMBuffer{
|
|
Format: &audio.Format{
|
|
NumChannels: numChannels,
|
|
SampleRate: tia.AverageSampleFreq,
|
|
},
|
|
I16: aw.buffer,
|
|
DataType: audio.DataTypeI16,
|
|
SourceBitDepth: bitDepth,
|
|
}
|
|
|
|
err = enc.Write(buf.AsIntBuffer())
|
|
if err != nil {
|
|
return fmt.Errorf("wavwriter: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Reset implements the television.AudioMixer interface
|
|
func (aw *WavWriter) Reset() {
|
|
}
|