yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
music_player.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_MUSIC_MUSIC_PLAYER_H
2#define YAZE_APP_EDITOR_MUSIC_MUSIC_PLAYER_H
3
4#include <array>
5#include <chrono>
6#include <memory>
7#include <string>
8#include <vector>
9
10#include "absl/status/status.h"
13#include "app/emu/emulator.h"
16
17namespace yaze {
18
19class Rom;
20
21namespace editor {
22namespace music {
23
28 bool is_playing = false;
29 bool is_paused = false;
31 float playback_speed = 1.0f;
32 uint32_t current_tick = 0;
34 float ticks_per_second = 0.0f;
35};
36
41 bool key_on = false;
42 int sample_index = 0;
43 uint16_t pitch = 0;
44 uint8_t volume_l = 0;
45 uint8_t volume_r = 0;
46 uint8_t gain = 0;
47 uint8_t adsr_state = 0; // 0: attack, 1: decay, 2: sustain, 3: release
48};
49
54 uint16_t sample_offset = 0; // Current write position in ring buffer (0-2047)
55 uint32_t frame_boundary = 0; // Position of last frame boundary
56 int8_t master_vol_l = 0; // Master volume left
57 int8_t master_vol_r = 0; // Master volume right
58 bool mute = false; // DSP mute flag
59 bool reset = false; // DSP reset flag
60 bool echo_enabled = false; // Echo writes enabled
61 uint16_t echo_delay = 0; // Echo delay setting
62};
63
68 uint64_t cycles = 0; // Total APU cycles executed
69 // Timer 0
70 bool timer0_enabled = false;
71 uint8_t timer0_counter = 0;
72 uint8_t timer0_target = 0;
73 // Timer 1
74 bool timer1_enabled = false;
75 uint8_t timer1_counter = 0;
76 uint8_t timer1_target = 0;
77 // Timer 2
78 bool timer2_enabled = false;
79 uint8_t timer2_counter = 0;
80 uint8_t timer2_target = 0;
81 // Port state
82 uint8_t port0_in = 0;
83 uint8_t port1_in = 0;
84 uint8_t port0_out = 0;
85 uint8_t port1_out = 0;
86};
87
92 bool is_playing = false;
93 uint32_t queued_frames = 0;
94 uint32_t queued_bytes = 0;
95 bool has_underrun = false;
96 int sample_rate = 0;
97 std::string backend_name;
98};
99
103enum class PlaybackMode {
104 Stopped, // No playback
105 Playing, // Active playback
106 Paused, // Playback paused
107 Previewing // Single note/segment preview
108};
109
123 public:
124 explicit MusicPlayer(zelda3::music::MusicBank* music_bank);
125 ~MusicPlayer();
126
127 // === Dependency Injection ===
128 void SetRom(Rom* rom);
129
138
148 void SetAudioExclusivityCallback(std::function<void(bool)> callback) {
149 audio_exclusivity_callback_ = std::move(callback);
150 }
151
152 // Access the emulator
154
155 // === Main Update Loop ===
162 void Update();
163
164 // === Playback Control ===
169 void PlaySong(int song_index);
170
174 void Pause();
175
179 void Resume();
180
184 void Stop();
185
189 void TogglePlayPause();
190
191 // === Preview Methods ===
195 void PreviewNote(const zelda3::music::MusicSong& song,
196 const zelda3::music::TrackEvent& event, int segment_index,
197 int channel_index);
198
202 void PreviewSegment(const zelda3::music::MusicSong& song, int segment_index);
203
207 void PreviewInstrument(int instrument_index);
208
212 void PreviewSample(int sample_index);
213
217 void PreviewCustomSong(int song_index);
218
219 // === Configuration ===
223 void SetVolume(float volume);
224
230 void SetPlaybackSpeed(float speed);
231
236 void SetInterpolationType(int type);
237
241 void SetDirectSpcMode(bool enabled);
242
246 void SeekToSegment(int segment_index);
247
248 // === State Access ===
249 PlaybackState GetState() const;
250 PlaybackMode GetMode() const { return mode_; }
251 ChannelState GetChannelState(int channel_index) const;
252 std::array<ChannelState, 8> GetChannelStates() const;
253
257 bool IsAudioReady() const;
258
262 bool IsPlaying() const { return mode_ == PlaybackMode::Playing; }
263
267 bool IsPaused() const { return mode_ == PlaybackMode::Paused; }
268
273
278 const zelda3::music::MusicSegment& segment, int channel_index,
279 uint16_t tick) const;
280
281 // === Debug Diagnostics ===
286
291
296
297 // === Debug Actions ===
301 void ClearAudioQueue();
302
306 void ResetDspBuffer();
307
311 void ForceNewFrame();
312
316 void ReinitAudio();
317
318 private:
319 // === Internal Helpers ===
320 bool EnsureAudioReady();
321 bool EnsurePreviewReady();
322 void InitializeDirectSpc();
324 void PlaySongDirect(int song_id);
325 void UploadSoundBankFromRom(uint32_t rom_offset);
326 void UploadSongToAram(const std::vector<uint8_t>& data, uint16_t aram_address);
327 uint32_t GetBankRomOffset(uint8_t bank) const;
328 int GetSongIndexInBank(int song_id, uint8_t bank) const;
329 float CalculateTicksPerSecond(uint8_t tempo) const;
330 uint32_t GetCurrentPlaybackTick() const;
331 uint8_t GetSongTempo(const zelda3::music::MusicSong& song) const;
332 void TransitionTo(PlaybackMode new_mode);
333
344
345 // === Dependencies ===
347 emu::Emulator* emulator_ = nullptr; // Injected main emulator
348 Rom* rom_ = nullptr;
349
350 // === Playback State ===
353
354 // === Playback Settings ===
355 bool use_direct_spc_ = true;
356 float volume_ = 1.0f;
357 int interpolation_type_ = 2; // Gaussian (authentic SNES)
358
359 // === Internal State ===
360 bool spc_initialized_ = false;
362 uint8_t current_spc_bank_ = 0xFF;
363
364 // === Timing ===
365 std::chrono::steady_clock::time_point playback_start_time_;
366 std::chrono::steady_clock::time_point last_frame_time_; // Frame pacing for Update()
368 float ticks_per_second_ = 0.0f;
370
371 // === Callback for audio exclusivity ===
372 std::function<void(bool)> audio_exclusivity_callback_;
373};
374
375} // namespace music
376} // namespace editor
377} // namespace yaze
378
379#endif // YAZE_APP_EDITOR_MUSIC_MUSIC_PLAYER_H
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
Handles audio playback for the music editor using the SNES APU emulator.
void PreviewSegment(const zelda3::music::MusicSong &song, int segment_index)
Preview a specific segment of a song.
ApuDebugStatus GetApuStatus() const
Get APU timing diagnostic status.
void Stop()
Stop playback completely.
void PreviewCustomSong(int song_index)
Preview a custom (modified) song from memory.
bool IsPlaying() const
Check if currently playing.
void ReinitAudio()
Reinitialize the audio system.
float CalculateTicksPerSecond(uint8_t tempo) const
void SetPlaybackSpeed(float speed)
Set the playback speed (0.25x to 2.0x).
bool IsPaused() const
Check if currently paused.
std::function< void(bool)> audio_exclusivity_callback_
void ForceNewFrame()
Force a DSP NewFrame() call.
ChannelState GetChannelState(int channel_index) const
int GetSongIndexInBank(int song_id, uint8_t bank) const
void SetInterpolationType(int type)
Set the DSP interpolation type for audio quality.
void SetVolume(float volume)
Set the master volume (0.0 to 1.0).
uint8_t GetSongTempo(const zelda3::music::MusicSong &song) const
std::chrono::steady_clock::time_point playback_start_time_
void Update()
Call once per frame to update playback state.
int GetPlayingSongIndex() const
Get the index of the currently playing song, or -1 if none.
void UploadSoundBankFromRom(uint32_t rom_offset)
void PrepareAudioPlayback()
Prepare audio pipeline for playback.
void Pause()
Pause the current playback.
uint32_t GetCurrentPlaybackTick() const
AudioQueueStatus GetAudioQueueStatus() const
Get audio queue diagnostic status.
std::array< ChannelState, 8 > GetChannelStates() const
void TransitionTo(PlaybackMode new_mode)
void PlaySong(int song_index)
Start playing a song by index.
void UploadSongToAram(const std::vector< uint8_t > &data, uint16_t aram_address)
DspDebugStatus GetDspStatus() const
Get DSP buffer diagnostic status.
void SetDirectSpcMode(bool enabled)
Enable/disable direct SPC mode (bypasses game CPU).
void Resume()
Resume paused playback.
void SetAudioExclusivityCallback(std::function< void(bool)> callback)
Set a callback to be called when audio playback starts/stops.
bool IsAudioReady() const
Check if the audio system is ready for playback.
uint32_t GetBankRomOffset(uint8_t bank) const
void PreviewNote(const zelda3::music::MusicSong &song, const zelda3::music::TrackEvent &event, int segment_index, int channel_index)
Preview a single note with the current instrument.
std::chrono::steady_clock::time_point last_frame_time_
void TogglePlayPause()
Toggle between play/pause states.
const zelda3::music::MusicInstrument * ResolveInstrumentForEvent(const zelda3::music::MusicSegment &segment, int channel_index, uint16_t tick) const
Resolve the instrument used at a specific tick in a track.
void SetEmulator(emu::Emulator *emulator)
Set the main emulator instance to use for playback.
PlaybackState GetState() const
zelda3::music::MusicBank * music_bank_
void ResetDspBuffer()
Reset the DSP sample buffer.
void PreviewSample(int sample_index)
Preview a raw BRR sample.
void PreviewInstrument(int instrument_index)
Preview an instrument at middle C.
void SeekToSegment(int segment_index)
Seek to a specific segment in the current song.
void ClearAudioQueue()
Clear the audio queue (stops sound immediately).
MusicPlayer(zelda3::music::MusicBank *music_bank)
A class for emulating and debugging SNES games.
Definition emulator.h:39
Manages the collection of songs, instruments, and samples from a ROM.
Definition music_bank.h:27
PlaybackMode
Playback mode for the music player.
APU timing diagnostic status for debug UI.
Audio queue diagnostic status for debug UI.
Represents the state of a single DSP channel for visualization.
DSP buffer diagnostic status for debug UI.
Represents the current playback state of the music player.
An instrument definition with ADSR envelope.
Definition song_data.h:358
A segment containing 8 parallel tracks.
Definition song_data.h:315
A complete song composed of segments.
Definition song_data.h:334
A single event in a music track (note, command, or control).
Definition song_data.h:247