Skip to content

Commit

Permalink
fallback if no audio devices can be found
Browse files Browse the repository at this point in the history
  • Loading branch information
thelolagemann committed Dec 30, 2024
1 parent c4467fc commit 7645320
Showing 1 changed file with 18 additions and 92 deletions.
110 changes: 18 additions & 92 deletions pkg/audio/sdl.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ package audio
// void AudioData(void *userdata, Uint8 *stream, int len);
import "C"
import (
"encoding/binary"
"github.com/thelolagemann/gomeboy/internal/gameboy"
"github.com/veandco/go-sdl2/sdl"
"os"
"reflect"
"time"
"unsafe"
)

Expand Down Expand Up @@ -76,6 +75,7 @@ func OpenAudio(g *gameboy.GameBoy, fb chan []byte) error {
}
}
frameBuffer = fb
gb = g

var err error
if audioDeviceID, err = sdl.OpenAudioDevice("", false, &sdl.AudioSpec{
Expand All @@ -85,25 +85,24 @@ func OpenAudio(g *gameboy.GameBoy, fb chan []byte) error {
Samples: bufferSize,
Callback: sdl.AudioCallback(C.AudioData),
}, nil, 0); err != nil {
// if we can't initialize any audio, we need to fall back to a dummy driver
// otherwise there won't be any output
go func() {
dummyBuffer := make([]C.Uint8, bufferSize*4) // Assuming 4 bytes per sample (32-bit float)
ticker := time.NewTicker(time.Second / time.Duration(sampleRate/bufferSize))
defer ticker.Stop()

for range ticker.C {
if gb != nil {
AudioData(nil, (*C.Uint8)(unsafe.Pointer(&dummyBuffer[0])), C.int(len(dummyBuffer)))
}
}
}()
return err
}
err = initWavFile() // Create WAV file at audio start
if err != nil {
return err
}
gb = g
sdl.PauseAudioDevice(audioDeviceID, false)

return nil
}

func CloseAudio() error {
err := finalizeWavFile() // Close WAV file at audio stop
if err != nil {
return err
}
sdl.PauseAudioDevice(audioDeviceID, false)

sdl.CloseAudioDevice(audioDeviceID)
return nil
}

Expand All @@ -112,81 +111,8 @@ var (
)

const (
bufferSize = 1634
sampleRate = 96000
)

const (
bufferSize = 1634
sampleRate = 96000
frameSize = 144 * 160 * 3
maxArraySize = 144 * 160 * 4
)

var (
wavFile *os.File
wavDataSize uint32
wavInitialized bool
audioSampleRate = 96000 // Adjust to your emulator's sample rate
audioNumChannels = 2 // Adjust to your emulator's number of channels (1 for mono, 2 for stereo)
audioBitsPerSample = 32 // Adjust to your emulator's bit depth per sample (typically 8 or 16)
)

func initWavFile() error {
var err error
wavFile, err = os.Create("output.wav")
if err != nil {
return err
}

// Write the WAV file header placeholder
var header [44]byte
copy(header[:4], "RIFF")
copy(header[8:12], "WAVE")
copy(header[12:16], "fmt ")
binary.LittleEndian.PutUint32(header[16:20], 16) // PCM header size
binary.LittleEndian.PutUint16(header[20:22], 1) // Audio format (1 = PCM)
binary.LittleEndian.PutUint16(header[22:24], uint16(audioNumChannels))
binary.LittleEndian.PutUint32(header[24:28], uint32(audioSampleRate))
binary.LittleEndian.PutUint32(header[28:32], uint32(audioSampleRate*audioNumChannels*(audioBitsPerSample/8)))
binary.LittleEndian.PutUint16(header[32:34], uint16(audioNumChannels*(audioBitsPerSample/8)))
binary.LittleEndian.PutUint16(header[34:36], uint16(audioBitsPerSample))
copy(header[36:40], "data")
// Data chunk size placeholder (to be filled in later)
_, err = wavFile.Write(header[:])
if err != nil {
return err
}

wavInitialized = true
return nil
}

func finalizeWavFile() error {
if wavFile == nil {
return nil
}

// Update the file size and data chunk size in the header
_, err := wavFile.Seek(4, 0)
if err != nil {
return err
}
if err := binary.Write(wavFile, binary.LittleEndian, uint32(36+wavDataSize)); err != nil {
return err
}

_, err = wavFile.Seek(40, 0)
if err != nil {
return err
}
if err := binary.Write(wavFile, binary.LittleEndian, wavDataSize); err != nil {
return err
}

err = wavFile.Close()
if err != nil {
return err
}

wavFile = nil
return nil
}

0 comments on commit 7645320

Please sign in to comment.