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 } }