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:
parent
89a72c6f33
commit
2921e23bca
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
19
README.md
19
README.md
@ -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.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user