1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-19 02:46:35 -05:00

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

View File

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

View File

@ -1,5 +1,11 @@
package Common package Common
import (
"bytes"
"encoding/binary"
"io"
)
// StreamReader allows you to read data from a byte array in various formats // StreamReader allows you to read data from a byte array in various formats
type StreamReader struct { type StreamReader struct {
data []byte data []byte
@ -40,6 +46,14 @@ func (v *StreamReader) GetWord() uint16 {
return result 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 // GetDword returns a uint32 dword from the stream
func (v *StreamReader) GetDword() uint32 { func (v *StreamReader) GetDword() uint32 {
result := uint32(v.data[v.position]) result := uint32(v.data[v.position])
@ -49,3 +63,22 @@ func (v *StreamReader) GetDword() uint32 {
v.position += 4 v.position += 4
return result 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)) 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 // PushDword writes a uint32 dword to the stream
func (v *StreamWriter) PushDword(val uint32) { func (v *StreamWriter) PushDword(val uint32) {
v.data = append(v.data, byte(val&0xFF)) 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)) v.data = append(v.data, byte((val>>24)&0xFF))
} }
// GetBytes returns the the byte slice of the underlying data
func (v *StreamWriter) GetBytes() []byte { func (v *StreamWriter) GetBytes() []byte {
return v.data return v.data
} }

View File

@ -30,7 +30,6 @@
package Compression package Compression
import ( import (
"bytes"
"log" "log"
"github.com/essial/OpenDiablo2/Common" "github.com/essial/OpenDiablo2/Common"
@ -345,7 +344,7 @@ func HuffmanDecompress(data []byte) []byte {
tail := buildList(sPrime[comptype]) tail := buildList(sPrime[comptype])
head := buildTree(tail) head := buildTree(tail)
var outputstream bytes.Buffer outputstream := Common.CreateStreamWriter()
bitstream := Common.CreateBitStream(data[1:]) bitstream := Common.CreateBitStream(data[1:])
var decoded int var decoded int
for true { for true {
@ -356,11 +355,11 @@ func HuffmanDecompress(data []byte) []byte {
break break
case 257: case 257:
newvalue := bitstream.ReadBits(8) newvalue := bitstream.ReadBits(8)
outputstream.WriteByte(byte(newvalue)) outputstream.PushByte(byte(newvalue))
tail = insertNode(tail, newvalue) tail = insertNode(tail, newvalue)
break break
default: default:
outputstream.WriteByte(byte(decoded)) outputstream.PushByte(byte(decoded))
break break
} }
if decoded == 256 { 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 package Compression
import ( import (
"bufio" "github.com/essial/OpenDiablo2/Common"
"bytes"
"encoding/binary"
"io"
) )
var sLookup = []int{ var sLookup = []int{
@ -33,25 +30,21 @@ func WavDecompress(data []byte, channelCount int) []byte {
Array1 := []int{0x2c, 0x2c} Array1 := []int{0x2c, 0x2c}
Array2 := make([]int, channelCount) Array2 := make([]int, channelCount)
input := bytes.NewReader(data) input := Common.CreateStreamReader(data)
var output bytes.Buffer output := Common.CreateStreamWriter()
outputWriter := bufio.NewWriter(&output) input.GetByte()
input.ReadByte()
shift, _ := input.ReadByte() shift := input.GetByte()
for i := 0; i < channelCount; i++ { for i := 0; i < channelCount; i++ {
temp := int16(0) temp := input.GetSWord()
binary.Read(input, binary.LittleEndian, &temp)
Array2[i] = int(temp) Array2[i] = int(temp)
binary.Write(outputWriter, binary.LittleEndian, &temp) output.PushSWord(temp)
} }
channel := channelCount - 1 channel := channelCount - 1
pos, _ := input.Seek(0, io.SeekCurrent) for input.GetPosition() < input.GetSize() {
input.Seek(pos, io.SeekStart) value := input.GetByte()
for pos < int64(input.Len()) {
value, _ := input.ReadByte()
if channelCount == 2 { if channelCount == 2 {
channel = 1 - channel channel = 1 - channel
@ -63,8 +56,7 @@ func WavDecompress(data []byte, channelCount int) []byte {
if Array1[channel] != 0 { if Array1[channel] != 0 {
Array1[channel]-- Array1[channel]--
} }
d := int16(Array2[channel]) output.PushSWord(int16(Array2[channel]))
binary.Write(outputWriter, binary.LittleEndian, &d)
break break
case 1: case 1:
Array1[channel] += 8 Array1[channel] += 8
@ -123,9 +115,7 @@ func WavDecompress(data []byte, channelCount int) []byte {
} }
} }
Array2[channel] = temp3 Array2[channel] = temp3
d := int16(temp3) output.PushSWord(int16(temp3))
binary.Write(outputWriter, binary.LittleEndian, &d)
Array1[channel] += sLookup2[value&0x1f] Array1[channel] += sLookup2[value&0x1f]
if Array1[channel] < 0 { 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.mapMpqFiles()
result.loadPalettes() result.loadPalettes()
result.loadSoundEntries() result.loadSoundEntries()
audioContext, err := audio.NewContext(48000) audioContext, err := audio.NewContext(22050)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -248,15 +248,13 @@ func (v *Engine) PlayBGM(song string) {
v.bgmAudio.Close() v.bgmAudio.Close()
} }
audioData := v.GetFile(song) 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)) d, err := wav.Decode(v.audioContext, audio.BytesReadSeekCloser(audioData))
if err != nil { if err != nil {
log.Fatal(err) 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 { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

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

View File

@ -35,25 +35,6 @@ The following extensions are recommended for working with this project:
* ms-vscode.go * ms-vscode.go
* defaltd.go-coverage-viewer * 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`, 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. then clicking on `Edit in settings.json`. Just paste that section where appropriate.