1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-01-14 21:36:40 -05:00

Added audio streaming capabilities (#471)

This commit is contained in:
Tim Sarbin 2020-06-27 02:49:27 -04:00 committed by GitHub
parent c6721432a6
commit 490c00b7b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 69 additions and 7 deletions

View File

@ -273,17 +273,37 @@ func (v *MPQ) ReadFile(fileName string) ([]byte, error) {
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
} }
fileBlockData.FileName = strings.ToLower(fileName) fileBlockData.FileName = strings.ToLower(fileName)
fileBlockData.calculateEncryptionSeed() fileBlockData.calculateEncryptionSeed()
mpqStream, err := CreateStream(v, fileBlockData, fileName) mpqStream, err := CreateStream(v, fileBlockData, fileName)
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
} }
buffer := make([]byte, fileBlockData.UncompressedFileSize) buffer := make([]byte, fileBlockData.UncompressedFileSize)
mpqStream.Read(buffer, 0, fileBlockData.UncompressedFileSize) mpqStream.Read(buffer, 0, fileBlockData.UncompressedFileSize)
return buffer, nil return buffer, nil
} }
func (v *MPQ) ReadFileStream(fileName string) (*MpqDataStream, error) {
fileBlockData, err := v.getFileBlockData(fileName)
if err != nil {
return nil, err
}
fileBlockData.FileName = strings.ToLower(fileName)
fileBlockData.calculateEncryptionSeed()
mpqStream, err := CreateStream(v, fileBlockData, fileName)
if err != nil {
return nil, err
}
return &MpqDataStream{stream: mpqStream}, nil
}
// ReadTextFile reads a file and returns it as a string // ReadTextFile reads a file and returns it as a string
func (v *MPQ) ReadTextFile(fileName string) (string, error) { func (v *MPQ) ReadTextFile(fileName string) (string, error) {
data, err := v.ReadFile(fileName) data, err := v.ReadFile(fileName)
@ -303,7 +323,7 @@ func (v *BlockTableEntry) calculateEncryptionSeed() {
} }
// GetFileList returns the list of files in this MPQ // GetFileList returns the list of files in this MPQ
func (v * MPQ) GetFileList() ([]string, error) { func (v *MPQ) GetFileList() ([]string, error) {
data, err := v.ReadFile("(listfile)") data, err := v.ReadFile("(listfile)")
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -0,0 +1,20 @@
package d2mpq
type MpqDataStream struct {
stream *Stream
}
func (m *MpqDataStream) Read(p []byte) (n int, err error) {
totalRead := m.stream.Read(p, 0, uint32(len(p)))
return int(totalRead), nil
}
func (m *MpqDataStream) Seek(offset int64, whence int) (int64, error) {
m.stream.CurrentPosition = uint32(offset + int64(whence))
return int64(m.stream.CurrentPosition), nil
}
func (m *MpqDataStream) Close() error {
m.stream = nil
return nil
}

View File

@ -86,7 +86,7 @@ func (v *Stream) Read(buffer []byte, offset, count uint32) uint32 {
toRead := count toRead := count
readTotal := uint32(0) readTotal := uint32(0)
for toRead > 0 { for toRead > 0 {
read := v.readInternal(buffer, offset, count) read := v.readInternal(buffer, offset, toRead)
if read == 0 { if read == 0 {
break break
} }

View File

@ -80,6 +80,17 @@ func LoadArchive(archivePath string) (*d2mpq.MPQ, error) {
return singleton.archiveManager.loadArchive(archivePath) return singleton.archiveManager.loadArchive(archivePath)
} }
func LoadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
verifyWasInit()
data, err := singleton.fileManager.loadFileStream(filePath)
if err != nil {
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
}
return data, err
}
func LoadFile(filePath string) ([]byte, error) { func LoadFile(filePath string) ([]byte, error) {
verifyWasInit() verifyWasInit()

View File

@ -1,6 +1,7 @@
package d2asset package d2asset
import ( import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
"strings" "strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2common"
@ -22,6 +23,18 @@ func createFileManager(config d2config.Configuration, archiveManager *archiveMan
return &fileManager{d2common.CreateCache(fileBudget), archiveManager, config} return &fileManager{d2common.CreateCache(fileBudget), archiveManager, config}
} }
func (fm *fileManager) loadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
filePath = fm.fixupFilePath(filePath)
archive, err := fm.archiveManager.loadArchiveForFile(filePath)
if err != nil {
return nil, err
}
return archive.ReadFileStream(filePath)
}
func (fm *fileManager) loadFile(filePath string) ([]byte, error) { func (fm *fileManager) loadFile(filePath string) ([]byte, error) {
filePath = fm.fixupFilePath(filePath) filePath = fm.fixupFilePath(filePath)
if value, found := fm.cache.Retrieve(filePath); found { if value, found := fm.cache.Retrieve(filePath); found {

View File

@ -32,9 +32,7 @@ func Initialize(audioProvider AudioProvider) error {
// PlayBGM plays an infinitely looping background track // PlayBGM plays an infinitely looping background track
func PlayBGM(song string) error { func PlayBGM(song string) error {
verifyWasInit() verifyWasInit()
go func() {
singleton.PlayBGM(song) singleton.PlayBGM(song)
}()
return nil return nil
} }

View File

@ -45,11 +45,11 @@ func (eap *AudioProvider) PlayBGM(song string) {
log.Panic(err) log.Panic(err)
} }
} }
audioData, err := d2asset.LoadFile(song) audioStream, err := d2asset.LoadFileStream(song)
if err != nil { if err != nil {
panic(err) panic(err)
} }
d, err := wav.Decode(eap.audioContext, audio.BytesReadSeekCloser(audioData)) d, err := wav.Decode(eap.audioContext, audioStream)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }