123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- package mz700_tape_wav_gen
- import (
- "encoding/binary"
- "fmt"
- "github.com/zenwerk/go-wave"
- "io"
- "math"
- )
- type MZ700TapeWavGen struct {
- wwr *wave.Writer
- longPulseData []int16
- shortPulseData []int16
- shortGapData []int16
- longGapData []int16
- silent1s []int16
- lastError error
- mc machineRelatedConfig
- hlv int16
- llv int16
- }
- func (g *MZ700TapeWavGen) Write(p []byte) (n int, err error) {
- l := len(p)
- for _, b := range p {
- g.WriteDataByte(b)
- }
- if g.lastError != nil {
- return 0, g.lastError
- }
- return l, nil
- }
- func NewMZ700TapeWavGen(f io.WriteCloser, machineType MachineType, invertPolarity bool) (*MZ700TapeWavGen, error) {
- g := &MZ700TapeWavGen{
- lastError: nil,
- mc: getMachineRelatedConfigByType(machineType),
- }
- if g.mc.Unsupported {
- return nil, fmt.Errorf("unsupported machine type")
- }
- if invertPolarity {
- g.llv = math.MaxInt16 / 2
- g.hlv = math.MinInt16 / 2
- } else {
- g.llv = math.MinInt16 / 2
- g.hlv = math.MaxInt16 / 2
- }
- wwrp := wave.WriterParam{
- Out: f,
- Channel: 1,
- SampleRate: 44100,
- BitsPerSample: 16,
- }
- var err error
- g.wwr, err = wave.NewWriter(wwrp)
- if err != nil {
- return nil, err
- }
- g.initPulseDataTemplate()
- return g, nil
- }
- func (g *MZ700TapeWavGen) initPulseDataTemplate() {
- g.longPulseData = make([]int16, g.mc.LongPulseSampleTotal)
- g.shortPulseData = make([]int16, g.mc.ShortPulseSampleTotal)
- for i := 0; i < g.mc.ShortPulseSampleHigh; i++ {
- g.shortPulseData[i] = g.hlv
- }
- for i := g.mc.ShortPulseSampleHigh; i < g.mc.ShortPulseSampleTotal; i++ {
- g.shortPulseData[i] = g.llv
- }
- for i := 0; i < g.mc.LongPulseSampleHigh; i++ {
- g.longPulseData[i] = g.hlv
- }
- for i := g.mc.LongPulseSampleHigh; i < g.mc.LongPulseSampleTotal; i++ {
- g.longPulseData[i] = g.llv
- }
- g.shortGapData = make([]int16, g.mc.ShortGapSize*g.mc.ShortPulseSampleTotal)
- g.longGapData = make([]int16, g.mc.LongGapSize*g.mc.ShortPulseSampleTotal)
- for j := 0; j < g.mc.ShortGapSize; j++ {
- for i := 0; i < g.mc.ShortPulseSampleHigh; i++ {
- g.shortGapData[j*g.mc.ShortPulseSampleTotal+i] = g.hlv
- }
- for i := g.mc.ShortPulseSampleHigh; i < g.mc.ShortPulseSampleTotal; i++ {
- g.shortGapData[j*g.mc.ShortPulseSampleTotal+i] = g.llv
- }
- }
- for j := 0; j < g.mc.LongGapSize; j++ {
- for i := 0; i < g.mc.ShortPulseSampleHigh; i++ {
- g.longGapData[j*g.mc.ShortPulseSampleTotal+i] = g.hlv
- }
- for i := g.mc.ShortPulseSampleHigh; i < g.mc.ShortPulseSampleTotal; i++ {
- g.longGapData[j*g.mc.ShortPulseSampleTotal+i] = g.llv
- }
- }
- g.silent1s = make([]int16, 44100)
- for i := 0; i < 44100; i++ {
- g.silent1s[i] = 0
- }
- }
- func (g *MZ700TapeWavGen) GetLastError() error {
- return g.lastError
- }
- func (g *MZ700TapeWavGen) WriteLongPulse() {
- _, err := g.wwr.WriteSample16(g.longPulseData)
- if err != nil {
- g.lastError = err
- }
- }
- func (g *MZ700TapeWavGen) WriteShortPulse() {
- _, err := g.wwr.WriteSample16(g.shortPulseData)
- if err != nil {
- g.lastError = err
- }
- }
- func (g *MZ700TapeWavGen) WriteBit(b bool) {
- if b {
- g.WriteLongPulse()
- } else {
- g.WriteShortPulse()
- }
- }
- func (g *MZ700TapeWavGen) WriteDataByte(b byte) {
- var mask uint8
- for mask = 0x80; mask >= 1; mask = mask >> 1 {
- if b&mask > 0 {
- g.WriteLongPulse()
- } else {
- g.WriteShortPulse()
- }
- }
- g.WriteLongPulse()
- }
- func (g *MZ700TapeWavGen) WriteGAP(isLong bool) {
- var err error
- if isLong {
- _, err = g.wwr.WriteSample16(g.longGapData)
- } else {
- _, err = g.wwr.WriteSample16(g.shortGapData)
- }
- if err != nil {
- g.lastError = err
- }
- }
- func (g *MZ700TapeWavGen) WriteTapeMark(isLong bool) {
- var tl int
- if isLong {
- tl = g.mc.LongTapemarkSize
- } else {
- tl = g.mc.ShortTapemarkSize
- }
- for i := 0; i < tl; i++ {
- g.WriteLongPulse()
- }
- for i := 0; i < tl; i++ {
- g.WriteShortPulse()
- }
- for i := 0; i < g.mc.TapemarkEndLongPulse; i++ {
- g.WriteLongPulse()
- }
- }
- func (g *MZ700TapeWavGen) Write256S() {
- for i := 0; i < 256; i++ {
- g.WriteShortPulse()
- }
- }
- func (g *MZ700TapeWavGen) WriteFileAttribute(attr byte) {
- g.WriteDataByte(attr)
- }
- // Return checksum
- func (g *MZ700TapeWavGen) WriteFilenameRaw(fnraw []byte) uint16 {
- chksum := GetByteSliceChecksum(fnraw)
- _, g.lastError = g.Write(fnraw)
- return chksum
- }
- // Return checksum. Sizes, addresses are in little endian.
- func (g *MZ700TapeWavGen) WriteUint16LittleEndian(n uint16) uint16 {
- b := make([]byte, 2)
- binary.LittleEndian.PutUint16(b, n)
- var chksum uint16 = 0
- chksum += GetSingleByteChecksum(b[0])
- chksum += GetSingleByteChecksum(b[1])
- _, g.lastError = g.Write(b)
- return chksum
- }
- // Return checksum. Checksums are in big endian.
- func (g *MZ700TapeWavGen) WriteUint16BigEndian(n uint16) uint16 {
- b := make([]byte, 2)
- binary.BigEndian.PutUint16(b, n)
- var chksum uint16 = 0
- chksum += GetSingleByteChecksum(b[0])
- chksum += GetSingleByteChecksum(b[1])
- _, g.lastError = g.Write(b)
- return chksum
- }
- // Return checksum
- func (g *MZ700TapeWavGen) WriteCommentRaw(rb []byte) uint16 {
- l := len(rb)
- if l > 104 {
- g.lastError = fmt.Errorf("comment too long")
- return 0
- }
- var wb []byte
- if l == 104 {
- wb = rb
- } else {
- wb = PaddingRawComment(rb)
- }
- chksum := GetByteSliceChecksum(wb)
- _, g.lastError = g.Write(wb)
- return chksum
- }
- func (g *MZ700TapeWavGen) WriteSilent1Second() {
- var err error
- _, err = g.wwr.WriteSample16(g.silent1s)
- if err != nil {
- g.lastError = err
- }
- }
- func (g *MZ700TapeWavGen) Close() error {
- err := g.wwr.Close()
- if err != nil {
- return err
- } else {
- return g.lastError
- }
- }
|