Got audio rendering working.

This commit is contained in:
Tim Sarbin 2019-10-25 17:09:07 -04:00
parent 89a72c6f33
commit 2921e23bca
9 changed files with 66 additions and 52 deletions

View File

@ -10,6 +10,7 @@ type BitStream struct {
bitCount int
}
// CreateBitStream creates a new BitStream
func CreateBitStream(newData []byte) *BitStream {
result := &BitStream{
data: newData,
@ -20,6 +21,7 @@ func CreateBitStream(newData []byte) *BitStream {
return result
}
// ReadBits reads the specified number of bits and returns the value
func (v *BitStream) ReadBits(bitCount int) int {
if bitCount > 16 {
log.Panic("Maximum BitCount is 16")
@ -32,6 +34,7 @@ func (v *BitStream) ReadBits(bitCount int) int {
return result
}
// PeekByte returns the current byte without adjusting the position
func (v *BitStream) PeekByte() int {
if !v.EnsureBits(8) {
return -1
@ -39,6 +42,7 @@ func (v *BitStream) PeekByte() int {
return v.current & 0xff
}
// EnsureBits ensures that the specified number of bits are available
func (v *BitStream) EnsureBits(bitCount int) bool {
if bitCount <= v.bitCount {
return true
@ -53,6 +57,7 @@ func (v *BitStream) EnsureBits(bitCount int) bool {
return true
}
// WasteBits dry-reads the specified number of bits
func (v *BitStream) WasteBits(bitCount int) {
v.current >>= bitCount
v.bitCount -= bitCount

View File

@ -4,6 +4,7 @@ import (
"github.com/hajimehoshi/ebiten"
)
// SceneInterface defines the function necessary for scene management
type SceneInterface interface {
Load()
Unload()

View File

@ -1,5 +1,11 @@
package Common
import (
"bytes"
"encoding/binary"
"io"
)
// StreamReader allows you to read data from a byte array in various formats
type StreamReader struct {
data []byte
@ -40,6 +46,14 @@ func (v *StreamReader) GetWord() uint16 {
return result
}
// GetSWord returns a int16 word from the stream
func (v *StreamReader) GetSWord() int16 {
var result int16
binary.Read(bytes.NewReader([]byte{v.data[v.position], v.data[v.position+1]}), binary.LittleEndian, &result)
v.position += 2
return result
}
// GetDword returns a uint32 dword from the stream
func (v *StreamReader) GetDword() uint32 {
result := uint32(v.data[v.position])
@ -49,3 +63,22 @@ func (v *StreamReader) GetDword() uint32 {
v.position += 4
return result
}
// ReadByte implements io.ByteReader
func (v *StreamReader) ReadByte() (byte, error) {
return v.GetByte(), nil
}
// Read implements io.Reader
func (v *StreamReader) Read(p []byte) (n int, err error) {
streamLength := v.GetSize()
for i := 0; ; i++ {
if v.GetPosition() >= streamLength {
return i, io.EOF
}
if i >= len(p) {
return i, nil
}
p[i] = v.GetByte()
}
}

View File

@ -24,6 +24,12 @@ func (v *StreamWriter) PushWord(val uint16) {
v.data = append(v.data, byte((val>>8)&0xFF))
}
// PushSWord writes a int16 word to the stream
func (v *StreamWriter) PushSWord(val int16) {
v.data = append(v.data, byte(val&0xFF))
v.data = append(v.data, byte((val>>8)&0xFF))
}
// PushDword writes a uint32 dword to the stream
func (v *StreamWriter) PushDword(val uint32) {
v.data = append(v.data, byte(val&0xFF))
@ -32,6 +38,7 @@ func (v *StreamWriter) PushDword(val uint32) {
v.data = append(v.data, byte((val>>24)&0xFF))
}
// GetBytes returns the the byte slice of the underlying data
func (v *StreamWriter) GetBytes() []byte {
return v.data
}

View File

@ -30,7 +30,6 @@
package Compression
import (
"bytes"
"log"
"github.com/essial/OpenDiablo2/Common"
@ -345,7 +344,7 @@ func HuffmanDecompress(data []byte) []byte {
tail := buildList(sPrime[comptype])
head := buildTree(tail)
var outputstream bytes.Buffer
outputstream := Common.CreateStreamWriter()
bitstream := Common.CreateBitStream(data[1:])
var decoded int
for true {
@ -356,11 +355,11 @@ func HuffmanDecompress(data []byte) []byte {
break
case 257:
newvalue := bitstream.ReadBits(8)
outputstream.WriteByte(byte(newvalue))
outputstream.PushByte(byte(newvalue))
tail = insertNode(tail, newvalue)
break
default:
outputstream.WriteByte(byte(decoded))
outputstream.PushByte(byte(decoded))
break
}
if decoded == 256 {
@ -368,5 +367,5 @@ func HuffmanDecompress(data []byte) []byte {
}
}
return outputstream.Bytes()
return outputstream.GetBytes()
}

View File

@ -1,10 +1,7 @@
package Compression
import (
"bufio"
"bytes"
"encoding/binary"
"io"
"github.com/essial/OpenDiablo2/Common"
)
var sLookup = []int{
@ -33,25 +30,21 @@ func WavDecompress(data []byte, channelCount int) []byte {
Array1 := []int{0x2c, 0x2c}
Array2 := make([]int, channelCount)
input := bytes.NewReader(data)
var output bytes.Buffer
outputWriter := bufio.NewWriter(&output)
input.ReadByte()
input := Common.CreateStreamReader(data)
output := Common.CreateStreamWriter()
input.GetByte()
shift, _ := input.ReadByte()
shift := input.GetByte()
for i := 0; i < channelCount; i++ {
temp := int16(0)
binary.Read(input, binary.LittleEndian, &temp)
temp := input.GetSWord()
Array2[i] = int(temp)
binary.Write(outputWriter, binary.LittleEndian, &temp)
output.PushSWord(temp)
}
channel := channelCount - 1
pos, _ := input.Seek(0, io.SeekCurrent)
input.Seek(pos, io.SeekStart)
for pos < int64(input.Len()) {
value, _ := input.ReadByte()
for input.GetPosition() < input.GetSize() {
value := input.GetByte()
if channelCount == 2 {
channel = 1 - channel
@ -63,8 +56,7 @@ func WavDecompress(data []byte, channelCount int) []byte {
if Array1[channel] != 0 {
Array1[channel]--
}
d := int16(Array2[channel])
binary.Write(outputWriter, binary.LittleEndian, &d)
output.PushSWord(int16(Array2[channel]))
break
case 1:
Array1[channel] += 8
@ -123,9 +115,7 @@ func WavDecompress(data []byte, channelCount int) []byte {
}
}
Array2[channel] = temp3
d := int16(temp3)
binary.Write(outputWriter, binary.LittleEndian, &d)
output.PushSWord(int16(temp3))
Array1[channel] += sLookup2[value&0x1f]
if Array1[channel] < 0 {
@ -137,5 +127,5 @@ func WavDecompress(data []byte, channelCount int) []byte {
}
}
}
return output.Bytes()
return output.GetBytes()
}

View File

@ -65,7 +65,7 @@ func CreateEngine() *Engine {
result.mapMpqFiles()
result.loadPalettes()
result.loadSoundEntries()
audioContext, err := audio.NewContext(48000)
audioContext, err := audio.NewContext(22050)
if err != nil {
log.Fatal(err)
}
@ -248,15 +248,13 @@ func (v *Engine) PlayBGM(song string) {
v.bgmAudio.Close()
}
audioData := v.GetFile(song)
//audioData2, _ := ioutil.ReadFile(`C:\Users\lunat\Desktop\D2\Extracted\data\global\music\introedit.wav`)
//log.Printf("%d, %d", len(audioData), len(audioData2))
d, err := wav.Decode(v.audioContext, audio.BytesReadSeekCloser(audioData))
if err != nil {
log.Fatal(err)
}
//s := audio.NewInfiniteLoop(d, int64(len(audioData)))
s := audio.NewInfiniteLoop(d, int64(len(audioData)))
v.bgmAudio, err = audio.NewPlayer(v.audioContext, d)
v.bgmAudio, err = audio.NewPlayer(v.audioContext, s)
if err != nil {
log.Fatal(err)
}

View File

@ -198,7 +198,7 @@ func decompressMulti(data []byte, expectedLength uint32) []byte {
panic("pk + mpqwav decompression not supported")
case 0x81:
sinput := Compression.HuffmanDecompress(data[1:])
sinput = Compression.WavDecompress(sinput, 1)
sinput = Compression.WavDecompress(sinput, 2)
tmp := make([]byte, len(sinput))
copy(tmp, sinput)
return tmp

View File

@ -35,25 +35,6 @@ The following extensions are recommended for working with this project:
* ms-vscode.go
* defaltd.go-coverage-viewer
For the Go extension, it is recommended you add the following to settings.json:
```json
"go.languageServerExperimentalFeatures": {
"format": true,
"autoComplete": true,
"rename": true,
"goToDefinition": true,
"hover": true,
"signatureHelp": true,
"goToTypeDefinition": true,
"goToImplementation": true,
"documentSymbols": true,
"workspaceSymbols": true,
"findReferences": true,
"diagnostics": true,
"documentLink": true
},
```
You can get to it by going to settings <kbd>Ctrl+,</kbd>, expanding `Extensions` and selecting `Go configuration`,
then clicking on `Edit in settings.json`. Just paste that section where appropriate.