mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2025-04-02 11:02:17 -04:00
curated package predated the standard errors package introduced in go1.13 the standard package does a better job of what curated attempted to do the change of package also gave me a opportunity to clean up the error messages a little bit
112 lines
3.1 KiB
Go
112 lines
3.1 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 digest
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"fmt"
|
|
|
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
|
"github.com/jetsetilly/gopher2600/hardware/television/signal"
|
|
)
|
|
|
|
// the length of the buffer we're using isn't really important. that said, it
|
|
// needs to be at least sha1.Size bytes in length.
|
|
const audioBufferLength = 1024 + sha1.Size
|
|
|
|
// to allow us to create digests on audio streams longer than
|
|
// audioBufferLength, we'll stuff the previous digest value into the first part
|
|
// of the buffer array and make sure we include it when we create the next
|
|
// digest value.
|
|
const audioBufferStart = sha1.Size
|
|
|
|
// Audio is an implementation of the television.AudioMixer interface with an
|
|
// embedded television for convenience. It periodically generates a SHA-1 value
|
|
// of the audio stream.
|
|
//
|
|
// Note that the use of SHA-1 is fine for this application because this is not a
|
|
// cryptographic task.
|
|
type Audio struct {
|
|
*television.Television
|
|
digest [sha1.Size]byte
|
|
buffer []uint8
|
|
bufferCt int
|
|
}
|
|
|
|
// NewAudio is the preferred method of initialisation for the Audio2Wav type.
|
|
func NewAudio(tv *television.Television) (*Audio, error) {
|
|
dig := &Audio{Television: tv}
|
|
|
|
// register ourselves as a protocol.AudioMixer
|
|
dig.AddAudioMixer(dig)
|
|
|
|
// create buffer
|
|
dig.buffer = make([]uint8, audioBufferLength)
|
|
dig.bufferCt = audioBufferStart
|
|
|
|
return dig, nil
|
|
}
|
|
|
|
// Hash implements digest.Digest interface.
|
|
func (dig Audio) Hash() string {
|
|
return fmt.Sprintf("%x", dig.digest)
|
|
}
|
|
|
|
// ResetDigest implements digest.Digest interface.
|
|
func (dig *Audio) ResetDigest() {
|
|
for i := range dig.digest {
|
|
dig.digest[i] = 0
|
|
}
|
|
}
|
|
|
|
// SetAudio implements the protocol.AudioMixer interface.
|
|
func (dig *Audio) SetAudio(sig []signal.SignalAttributes) error {
|
|
for _, s := range sig {
|
|
if s&signal.AudioUpdate != signal.AudioUpdate {
|
|
continue
|
|
}
|
|
d := uint8((s & signal.AudioChannel0) >> signal.AudioChannel0Shift)
|
|
|
|
dig.buffer[dig.bufferCt] = d
|
|
|
|
dig.bufferCt++
|
|
if dig.bufferCt >= audioBufferLength {
|
|
return dig.flushAudio()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Reset implements the protocol.AudioMixer interface.
|
|
func (dig *Audio) Reset() {
|
|
_ = dig.flushAudio()
|
|
}
|
|
|
|
func (dig *Audio) flushAudio() error {
|
|
dig.digest = sha1.Sum(dig.buffer)
|
|
n := copy(dig.buffer, dig.digest[:])
|
|
if n != len(dig.digest) {
|
|
return fmt.Errorf("digest: audio: digest error while flushing audio stream")
|
|
}
|
|
dig.bufferCt = audioBufferStart
|
|
return nil
|
|
}
|
|
|
|
// EndMixing implements the protocol.AudioMixer interface.
|
|
func (dig *Audio) EndMixing() error {
|
|
return nil
|
|
}
|