137 lines
5.9 KiB
C++
137 lines
5.9 KiB
C++
// iigs/sound.h - convenience wrappers for the SoundManager toolset.
|
|
//
|
|
// What's here today: the simplest correct wrappers around the existing
|
|
// toolbox calls - SysBeep, FFStartSound on a pre-loaded DOC RAM region,
|
|
// FFStopSound, FFSoundDoneStatus polling, plus iigsLoadDocSample (a
|
|
// thin wrapper around WriteRamBlock that stages caller-RAM bytes into
|
|
// the Ensoniq DOC's 64 KB audio RAM) and iigsSoundProbeInit (a small
|
|
// MMStartUp + SoundStartUp helper so CLI-style sound demos don't have
|
|
// to pull in startdesk()'s 16-tool chain). Lower-level than
|
|
// std::sound but a thin layer above iigs/toolbox.h.
|
|
//
|
|
// Phase 1.6 (2026-06-01) corrected the IigsSoundParmT layout to match
|
|
// ORCA's authoritative SoundParamBlock (18 bytes). The previous 6-byte
|
|
// struct was silently wrong; any caller relying on the old layout MUST
|
|
// migrate. The new layout matches the Apple SoundManager reference
|
|
// (Apple Tech Note #76) exactly.
|
|
//
|
|
// Phase 2.4 (2026-06-01) added iigsLoadDocSample so callers can stage
|
|
// in-RAM waveform bytes directly without going through the raw
|
|
// WriteRamBlock toolbox call.
|
|
//
|
|
// Caller must have started up the SoundManager before any of these
|
|
// functions are called. startdesk() in iigs/desktop.h does that for
|
|
// you; for a CLI-style sound demo where a full desktop is overkill,
|
|
// call iigsSoundProbeInit() yourself first.
|
|
#ifndef IIGS_SOUND_H
|
|
#define IIGS_SOUND_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
// SoundParamBlock consumed by FFStartSound. Layout MUST match ORCA's
|
|
// authoritative SoundParamBlock (tools/orca-c/ORCACDefs/sound.h:69):
|
|
// 18 bytes total, field order load-bearing. Do NOT reorder; the
|
|
// toolset reads by offset.
|
|
//
|
|
// waveStart is a 24/32-bit BYTE address into DOC RAM (NOT a 256-byte
|
|
// page index, as the previous incorrect layout assumed). Pass the
|
|
// byte offset where the sample begins in DOC RAM.
|
|
// waveSize is in 256-byte pages.
|
|
// volSetting's high byte must be zero (DOC volume is u8).
|
|
// nextWavePtr chains additional waves; NULL terminates.
|
|
typedef struct IigsSoundParmT {
|
|
void * waveStart; // 4B: DOC RAM byte address of wave
|
|
uint16_t waveSize; // 2B: wave length in 256-byte pages
|
|
uint16_t freqOffset; // 2B: pitch offset
|
|
uint16_t docBuffer; // 2B: DOC buffer start, low byte = 0
|
|
uint16_t bufferSize; // 2B: DOC buffer size, low byte = 0
|
|
struct IigsSoundParmT * nextWavePtr; // 4B: next wave in chain, NULL = end
|
|
uint16_t volSetting; // 2B: DOC volume (high byte = 0)
|
|
} IigsSoundParmT;
|
|
|
|
_Static_assert(sizeof(IigsSoundParmT) == 18, "IigsSoundParmT must be 18 bytes per ORCA SoundParamBlock");
|
|
|
|
|
|
// ---- one-call wrappers --------------------------------------------
|
|
|
|
// Lightweight startup helper for sound-only demos that don't want to
|
|
// drag in startdesk()'s full 16-tool chain. Calls MMStartUp +
|
|
// SoundStartUp in the right order. Safe to call after the Loader
|
|
// already started up Memory Manager (the toolset reference-counts).
|
|
// Returns the userId allocated by MMStartUp; the caller can pass it
|
|
// to NewHandle/similar if it needs to allocate from the same pool.
|
|
//
|
|
// Pair with iigsSoundProbeShutdown() at exit, or just exit straight to
|
|
// GS/OS - Finder will clean up the tool startup chain on app
|
|
// termination.
|
|
unsigned short iigsSoundProbeInit(void);
|
|
|
|
|
|
// Shut down the SoundManager started by iigsSoundProbeInit(). Optional
|
|
// - Finder will reclaim everything on app exit.
|
|
void iigsSoundProbeShutdown(void);
|
|
|
|
|
|
// Stage a waveform from caller RAM into the Ensoniq DOC's 64 KB audio
|
|
// RAM. Wraps the WriteRamBlock toolbox call (tool 0x0908, set 0x08).
|
|
//
|
|
// SoundManager must already be started up (see iigsSoundProbeInit() or
|
|
// startdesk()). Returns nothing; WriteRamBlock has no error result and
|
|
// silently truncates if docOffset + size overflows DOC RAM. Use
|
|
// iigsPlayDocSample() afterwards to play the staged region.
|
|
//
|
|
// wave pointer to the raw sample bytes (signed 8-bit, DOC's
|
|
// native format). Reads `size` bytes starting here.
|
|
// size number of bytes to copy. Must be a non-zero multiple
|
|
// of 256 - DOC RAM addressing is page-aligned (256-byte
|
|
// pages) and FFStartSound consumes lengths in pages.
|
|
// docOffset destination BYTE offset into DOC RAM (0..65535). The
|
|
// low byte should be zero (page-aligned).
|
|
void iigsLoadDocSample(const signed char *wave, unsigned short size, unsigned short docOffset);
|
|
|
|
|
|
// System beep. Same as the toolbox SysBeep but named consistently.
|
|
void iigsBeep(void);
|
|
|
|
|
|
// Play a sample that has already been written into DOC RAM. Returns
|
|
// immediately (asynchronous); use iigsSoundWait() to block until done.
|
|
//
|
|
// Phase 1.6 (2026-06-01) BREAKING CHANGE: the signature has been
|
|
// rewritten to match the corrected struct. Old callers passed
|
|
// (docPage, pages, pitch, volume, channel) which silently produced
|
|
// wrong DOC RAM addresses (the old waveStart was 1 byte, not 4).
|
|
//
|
|
// docAddr DOC RAM BYTE address where the sample begins (NOT a
|
|
// 256-byte page index). Multiply your old "docPage" by
|
|
// 256 to get the equivalent byte address.
|
|
// pages length in 256-byte pages.
|
|
// freqOffset DOC pitch offset.
|
|
// volume 0..255 (placed in volSetting, high byte zeroed).
|
|
// genNum generator number (0..15) in the low byte, priority
|
|
// (0..255) in the high byte. This is FFStartSound's
|
|
// arg0 - the channel is NOT in the struct anymore.
|
|
void iigsPlayDocSample(void *docAddr, uint16_t pages,
|
|
uint16_t freqOffset, uint8_t volume,
|
|
uint16_t genNum);
|
|
|
|
|
|
// Stop playback on the given generator (0..15). Pass 0xFF to stop
|
|
// all generators.
|
|
void iigsSoundStop(uint8_t generator);
|
|
|
|
|
|
// Block until generator 0 finishes playing. Polls FFSoundDoneStatus.
|
|
void iigsSoundWait(void);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // IIGS_SOUND_H
|