Audio Phase 2 (AUDIO_FIDELITY F1/F2/F13/F14): full-zone soundbank -- key-splits,
layers, baked tuning, loop regions, release fades Extractor rewrite (tools/sf2extract.py): every sample-bearing instrument zone becomes a SAMPLEINFO slot -- 603 zones / 241 presets (68/115 + 94/126 multi- zone, matching the audit exactly). Per zone: keyRange(43), sampleModes(54), SBK samplePitch(55) + rootKey(58) + coarse/fineTune(51/52), attenuation(48, INVERTED SBK scale, 0.375 dB/step [T3], baked into the PCM), releaseVolEnv(38), pan(17), shdr loop region. F2 pitch (algebraically exact): WAV rate = round(44100 * 2^(((6000 - rootCents) + tune)/1200)) -- EMU8000 v1 base 44100. Cross-checks: FootFall 17300 Hz (the audit's +4.2 st), MissileLoaded low zone 88200 (-24 st), Warnings01 8-way klaxon split w/ 3 looped zones, Death01 162 Hz extremes. F1 zone selection: SetupPatch/PlayNote take the authored note; attach/play only zones whose [keyLo,keyHi] contains it (detach the rest so a rewound source can't replay a stale buffer). Live-verified: LaserLoaded/ MissileLoaded note 36 -> low clunk zone, note 84 -> high blip zone (pitch 4); LaserCFire plays all 3 authored layers incl the looping sustain. Stereo-pair zones pan via listener-relative AL_POSITION (distance model is AL_NONE). MAX_PRESET_SAMPLES=25 (AllExplosion); fixed PRESET_isImplemented's >=5 bound. F13 loops + releases: authored [loopStart,loopEnd] applied via AL_SOFT_loop_points at buffer load (0 rejections; kills the latent boom-loop on MechExplosion's 1.5% sustain slice + the ~2.4 Hz LaserBSustain wrap tick); StopNote now honors the authored releaseVolEnv (1.1-3.9 s on ~20 looping presets) with a dB-linear fade serviced from AudioHead::Execute; restarts reclaim fading sources. One-shots keep the instant stop (faithful). Regression (40s drive+fire): stable, loop points accepted, key-splits + layers verified in the delivery trace, chirp still dead, footfalls fire. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
fc7f311771
commit
691e88569a
@@ -158,6 +158,21 @@ void
|
||||
if (getenv("BT_AUDIO_SPATIAL")) { static long s_hx=0; if ((++s_hx % 300)==0)
|
||||
DEBUG_STREAM << "[audioclock] frame=" << audioFrameCount << " execs=" << s_hx << "\n" << std::flush; }
|
||||
|
||||
// (task #50, AUDIO_FIDELITY F13) service the authored release fades
|
||||
// registered by PatchLevelOfDetail::StopNote (dB-linear note-off ramps).
|
||||
{
|
||||
extern void PRESET_serviceReleaseFades(float elapsed_seconds);
|
||||
static long s_lastFadeTicks = 0;
|
||||
long now_ticks = Now().ticks;
|
||||
if (s_lastFadeTicks != 0 && now_ticks > s_lastFadeTicks)
|
||||
{
|
||||
double tps = (double)SystemClock::GetTicksPerSecond();
|
||||
if (tps <= 0.0) tps = 1000.0;
|
||||
PRESET_serviceReleaseFades((float)((now_ticks - s_lastFadeTicks) / tps));
|
||||
}
|
||||
s_lastFadeTicks = now_ticks;
|
||||
}
|
||||
|
||||
//set current listener orientation
|
||||
Vector3D headVelocity;
|
||||
|
||||
|
||||
@@ -935,7 +935,7 @@ void
|
||||
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
|
||||
Check(patch_resource);
|
||||
patch_resource->SetDistance(GetDistanceToSource());
|
||||
patch_resource->SetupPatch(channelSet);
|
||||
patch_resource->SetupPatch(channelSet, (int)GetCurrentNoteValue());
|
||||
|
||||
{ // apply the requested note's pitch to the freshly attached sources
|
||||
float note_pitch = BTNotePitchFactor((int)GetCurrentNoteValue());
|
||||
@@ -999,7 +999,7 @@ void
|
||||
//
|
||||
//TODO: Start OpenAL source playing
|
||||
// channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
|
||||
patch_resource->PlayNote(channelSet);
|
||||
patch_resource->PlayNote(channelSet, (int)GetCurrentNoteValue());
|
||||
|
||||
#if 0
|
||||
Tell("On " << (int)GetCurrentNoteValue() << "\n");
|
||||
@@ -1231,7 +1231,7 @@ void
|
||||
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
|
||||
Check(patch_resource);
|
||||
patch_resource->SetDistance(GetDistanceToSource());
|
||||
patch_resource->SetupPatch(channelSet);
|
||||
patch_resource->SetupPatch(channelSet, (int)GetCurrentNoteValue());
|
||||
|
||||
{ // apply the requested note's pitch to the freshly attached sources
|
||||
float note_pitch = BTNotePitchFactor((int)GetCurrentNoteValue());
|
||||
@@ -1332,7 +1332,7 @@ void
|
||||
Check(channel);
|
||||
channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
|
||||
}*/
|
||||
patch_resource->PlayNote(channelSet);
|
||||
patch_resource->PlayNote(channelSet, (int)GetCurrentNoteValue());
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1755,7 +1755,7 @@ void
|
||||
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
|
||||
Check(patch_resource);
|
||||
patch_resource->SetDistance(GetDistanceToSource());
|
||||
patch_resource->SetupPatch(channelSet);
|
||||
patch_resource->SetupPatch(channelSet, (int)GetCurrentNoteValue());
|
||||
|
||||
{ // apply the requested note's pitch to the freshly attached sources
|
||||
float note_pitch = BTNotePitchFactor((int)GetCurrentNoteValue());
|
||||
@@ -1918,7 +1918,7 @@ void
|
||||
channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
|
||||
}
|
||||
}*/
|
||||
patch_resource->PlayNote(channelSet);
|
||||
patch_resource->PlayNote(channelSet, (int)GetCurrentNoteValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
+149
-14
@@ -9,6 +9,100 @@
|
||||
#include "..\munga\namelist.h"
|
||||
#include "openal/al.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Release fades ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// (task #50, AUDIO_FIDELITY F13) ~20 looping presets author a releaseVolEnv of
|
||||
// 1.1-3.9 s the AWE32 applied as a note-off fade while the loop continued;
|
||||
// StopNote registers a dB-linear ramp here instead of cutting. Serviced once
|
||||
// per frame from AudioHead::Execute; a fade finishing (or being reclaimed by a
|
||||
// restart) stops + rewinds the source so the next SetupPatch sees AL_INITIAL.
|
||||
//
|
||||
namespace
|
||||
{
|
||||
struct ReleaseFade
|
||||
{
|
||||
ALuint source;
|
||||
float gain0;
|
||||
float duration;
|
||||
float elapsed;
|
||||
bool active;
|
||||
};
|
||||
const int MAX_RELEASE_FADES = 64;
|
||||
ReleaseFade s_releaseFades[MAX_RELEASE_FADES];
|
||||
|
||||
void FinishFade(ReleaseFade &fade)
|
||||
{
|
||||
alSourceStop(fade.source);
|
||||
alSourceRewind(fade.source);
|
||||
alSourcef(fade.source, AL_GAIN, fade.gain0);
|
||||
fade.active = false;
|
||||
}
|
||||
|
||||
void StartReleaseFade(ALuint source, float duration)
|
||||
{
|
||||
for (int i = 0; i < MAX_RELEASE_FADES; i++)
|
||||
{
|
||||
if (s_releaseFades[i].active && s_releaseFades[i].source == source)
|
||||
{
|
||||
return; // already releasing
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < MAX_RELEASE_FADES; i++)
|
||||
{
|
||||
if (!s_releaseFades[i].active)
|
||||
{
|
||||
ReleaseFade &fade = s_releaseFades[i];
|
||||
fade.source = source;
|
||||
alGetSourcef(source, AL_GAIN, &fade.gain0);
|
||||
fade.duration = duration;
|
||||
fade.elapsed = 0.0f;
|
||||
fade.active = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// table full -- fall back to the instant cut
|
||||
alSourceStop(source);
|
||||
alSourceRewind(source);
|
||||
}
|
||||
|
||||
// A restart wants this source back NOW: finalize any fade so the caller
|
||||
// sees AL_INITIAL with the pre-fade gain restored.
|
||||
void ReclaimFadingSource(ALuint source)
|
||||
{
|
||||
for (int i = 0; i < MAX_RELEASE_FADES; i++)
|
||||
{
|
||||
if (s_releaseFades[i].active && s_releaseFades[i].source == source)
|
||||
{
|
||||
FinishFade(s_releaseFades[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PRESET_serviceReleaseFades(float elapsed_seconds)
|
||||
{
|
||||
for (int i = 0; i < MAX_RELEASE_FADES; i++)
|
||||
{
|
||||
ReleaseFade &fade = s_releaseFades[i];
|
||||
if (!fade.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fade.elapsed += elapsed_seconds;
|
||||
if (fade.elapsed >= fade.duration)
|
||||
{
|
||||
FinishFade(fade);
|
||||
}
|
||||
else
|
||||
{
|
||||
// dB-linear ramp to -96 dB over the authored release time
|
||||
float attenuation = powf(10.0f, -4.8f * (fade.elapsed / fade.duration));
|
||||
alSourcef(fade.source, AL_GAIN, fade.gain0 * attenuation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#if DEBUG_LEVEL>0
|
||||
@@ -27,7 +121,10 @@ PatchLevelOfDetail::PatchLevelOfDetail(PlugStream *stream):
|
||||
MemoryStream_Read(stream, &patchID);
|
||||
MemoryStream_Read(stream, &maxMIDIFilterCutoff);
|
||||
|
||||
Warn(GetVoiceCount() > 4); // HACK - AWE appears to only play 1st 4 voices
|
||||
// (task #50) the AWE 4-voice comment applied to layers SHARING a key range;
|
||||
// full-zone presets legitimately carry up to MAX_PRESET_SAMPLES zones
|
||||
// (key-splits select at most a few per note).
|
||||
Warn(GetVoiceCount() > MAX_PRESET_SAMPLES);
|
||||
|
||||
#ifdef LAB_ONLY
|
||||
setupCount = 0;
|
||||
@@ -119,7 +216,7 @@ Logical
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
PatchLevelOfDetail::SetupPatch(SourceSet sourceSet)
|
||||
PatchLevelOfDetail::SetupPatch(SourceSet sourceSet, int note)
|
||||
{
|
||||
// Check(this);
|
||||
//// Check(channel);
|
||||
@@ -129,30 +226,44 @@ void
|
||||
// #endif
|
||||
SAMPLEINFO info;
|
||||
|
||||
//Attach buffers
|
||||
// (task #50, AUDIO_FIDELITY F1) the authored MIDI note SELECTS zones:
|
||||
// attach only samples whose [keyLo,keyHi] contains the note (key-splits
|
||||
// pick one band, layers attach together); detach the rest so a rewound
|
||||
// source can't replay a stale buffer from a previous note.
|
||||
for (int i=0; i < sourceSet.count; i++)
|
||||
{
|
||||
info = PRESET_getSampleInfo(bankID,patchID,i);
|
||||
if (info.bufferIndex >= 0)
|
||||
{
|
||||
ReclaimFadingSource(sourceSet.sources[i]);
|
||||
|
||||
ALenum sourceState;
|
||||
alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &sourceState);
|
||||
|
||||
bool zone_matches = (note >= info.keyLo && note <= info.keyHi);
|
||||
|
||||
if (getenv("BT_AUDIO_SPATIAL")) { static int s_se=0; if (s_se++<200)
|
||||
DEBUG_STREAM << "[audio] SetupPatch ENTRY bank=" << (int)bankID << " patch=" << (int)patchID << " src=" << sourceSet.sources[i]
|
||||
<< " file=" << (info.file?info.file:"?")
|
||||
<< " file=" << (info.file?info.file:"?") << " note=" << note << (zone_matches?"":" ZONESKIP")
|
||||
<< " state=" << sourceState << " (INITIAL=" << AL_INITIAL << ")" << "\n" << std::flush; }
|
||||
|
||||
if (sourceState == AL_INITIAL)
|
||||
{
|
||||
alSourcei(sourceSet.sources[i],AL_BUFFER,AL_getBuffer(info.bufferIndex));
|
||||
alSourcei(sourceSet.sources[i],AL_BUFFER,
|
||||
zone_matches ? AL_getBuffer(info.bufferIndex) : 0);
|
||||
{ static int s_a=0; if (getenv("BT_AUDIO_LOG") && s_a++<24) DEBUG_STREAM << "[audio] SetupPatch src=" << sourceSet.sources[i] << " file=" << (info.file?info.file:"?") << " loop=" << (info.loop==ForceStatic?0:1) << "\n" << std::flush; }
|
||||
alSourcei(sourceSet.sources[i],AL_SOURCE_RELATIVE,AL_TRUE);
|
||||
|
||||
AudioRenderer *render = application->GetAudioRenderer();
|
||||
AudioHead *head = render->GetAudioHead();
|
||||
|
||||
alSource3f(sourceSet.sources[i],AL_POSITION,0,0,0);
|
||||
// (F1) authored stereo pairs: pan hard-left/right zones via a
|
||||
// listener-relative offset (the distance model is AL_NONE, so
|
||||
// this affects direction only, never gain).
|
||||
float pan_x =
|
||||
(info.chan == CHANNEL_LEFT) ? -0.5f :
|
||||
(info.chan == CHANNEL_RIGHT) ? 0.5f : 0.0f;
|
||||
alSource3f(sourceSet.sources[i],AL_POSITION,pan_x,0,0);
|
||||
alSource3f(sourceSet.sources[i],AL_VELOCITY,0,0,0);
|
||||
|
||||
if (info.loop == ForceStatic)
|
||||
@@ -180,7 +291,7 @@ void
|
||||
#endif*/
|
||||
}
|
||||
|
||||
void PatchLevelOfDetail::PlayNote(SourceSet sourceSet)
|
||||
void PatchLevelOfDetail::PlayNote(SourceSet sourceSet, int note)
|
||||
{
|
||||
if (sourceSet.count > 0 && sourceSet.sources != NULL)
|
||||
{
|
||||
@@ -189,13 +300,21 @@ void PatchLevelOfDetail::PlayNote(SourceSet sourceSet)
|
||||
|
||||
for (int i = 0; i < sourceSet.count; i++)
|
||||
{
|
||||
// (F1) play only the zones SetupPatch attached for this note
|
||||
ALint attached = 0;
|
||||
alGetSourcei(sourceSet.sources[i], AL_BUFFER, &attached);
|
||||
if (attached == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ALenum state;
|
||||
alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &state);
|
||||
|
||||
if (state != AL_PLAYING)
|
||||
{
|
||||
alSourcePlay(sourceSet.sources[i]);
|
||||
{ static int s_p=0; if (getenv("BT_AUDIO_LOG") && s_p++<30) DEBUG_STREAM << "[audio] PlayNote alSourcePlay src=" << sourceSet.sources[i] << "\n" << std::flush; }
|
||||
{ static int s_p=0; if (getenv("BT_AUDIO_LOG") && s_p++<30) DEBUG_STREAM << "[audio] PlayNote alSourcePlay src=" << sourceSet.sources[i] << " note=" << note << "\n" << std::flush; }
|
||||
}
|
||||
|
||||
ALenum error = alGetError();
|
||||
@@ -213,8 +332,24 @@ void PatchLevelOfDetail::StopNote(SourceSet sourceSet)
|
||||
if (getenv("BT_AUDIO_LOG")) { static int s_s=0; if (s_s++<400) { DEBUG_STREAM << "[audio] StopNote"; for (int _i=0;_i<sourceSet.count;_i++) DEBUG_STREAM << " src=" << sourceSet.sources[_i]; DEBUG_STREAM << "\n" << std::flush; } }
|
||||
if (sourceSet.count >0 && sourceSet.sources != NULL)
|
||||
{
|
||||
alSourceStopv(sourceSet.count, sourceSet.sources);
|
||||
alSourceRewindv(sourceSet.count, sourceSet.sources);
|
||||
// (task #50, AUDIO_FIDELITY F13) honor the authored releaseVolEnv:
|
||||
// a playing zone with a release time fades out dB-linearly instead of
|
||||
// cutting; everything else stops instantly (faithful for one-shots).
|
||||
for (int i = 0; i < sourceSet.count; i++)
|
||||
{
|
||||
SAMPLEINFO info = PRESET_getSampleInfo(bankID,patchID,i);
|
||||
ALenum state;
|
||||
alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &state);
|
||||
if (state == AL_PLAYING && info.releaseSec > 0.05f)
|
||||
{
|
||||
StartReleaseFade(sourceSet.sources[i], info.releaseSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
alSourceStop(sourceSet.sources[i]);
|
||||
alSourceRewind(sourceSet.sources[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +403,7 @@ Logical
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
PatchResource::SetupPatch(SourceSet sourceSet)
|
||||
PatchResource::SetupPatch(SourceSet sourceSet, int note)
|
||||
{
|
||||
Check(this);
|
||||
// Check(channel);
|
||||
@@ -277,10 +412,10 @@ void
|
||||
Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail());
|
||||
|
||||
Check(patch_level_of_detail);
|
||||
patch_level_of_detail->SetupPatch(sourceSet);
|
||||
patch_level_of_detail->SetupPatch(sourceSet, note);
|
||||
}
|
||||
|
||||
void PatchResource::PlayNote(SourceSet sourceSet)
|
||||
void PatchResource::PlayNote(SourceSet sourceSet, int note)
|
||||
{
|
||||
Check(this);
|
||||
// Check(channel);
|
||||
@@ -289,7 +424,7 @@ void PatchResource::PlayNote(SourceSet sourceSet)
|
||||
Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail());
|
||||
|
||||
Check(patch_level_of_detail);
|
||||
patch_level_of_detail->PlayNote(sourceSet);
|
||||
patch_level_of_detail->PlayNote(sourceSet, note);
|
||||
}
|
||||
|
||||
void PatchResource::StopNote(SourceSet sourceSet)
|
||||
|
||||
@@ -26,12 +26,24 @@ struct SAMPLEINFO
|
||||
const char *file;
|
||||
SampleChannel chan;
|
||||
SampleLoop loop;
|
||||
// (task #50, AUDIO_FIDELITY F1/F13) full-zone metadata from the SF2 banks:
|
||||
// the authored MIDI note SELECTS zones by [keyLo,keyHi]; loop regions are
|
||||
// sub-ranges in sample frames (AL_SOFT_loop_points); releaseSec is the
|
||||
// authored releaseVolEnv fade applied on Stop instead of an instant cut.
|
||||
int keyLo;
|
||||
int keyHi;
|
||||
int loopStart;
|
||||
int loopEnd;
|
||||
float releaseSec;
|
||||
};
|
||||
|
||||
// AllExplosion (bank2 p125) authors 25 layered zones -- the largest preset.
|
||||
const int MAX_PRESET_SAMPLES = 25;
|
||||
|
||||
struct PRESETINFO
|
||||
{
|
||||
int sampleNum;
|
||||
SAMPLEINFO samples[5];
|
||||
SAMPLEINFO samples[MAX_PRESET_SAMPLES];
|
||||
bool is3d;
|
||||
};
|
||||
|
||||
@@ -42,6 +54,10 @@ int PRESET_getNumSamples(int bank, int preset);
|
||||
SAMPLEINFO PRESET_getSampleInfo(int bank, int preset, int sampleInd);
|
||||
void PRESET_setBufferIndex(int bank, int preset, int sampleInd, int index);
|
||||
|
||||
// (task #50, AUDIO_FIDELITY F13) authored release fades: StopNote registers a
|
||||
// dB-linear gain ramp instead of cutting; AudioHead::Execute services them.
|
||||
void PRESET_serviceReleaseFades(float elapsed_seconds);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
typedef MIDIValue SBKPatchID;
|
||||
@@ -59,7 +75,7 @@ public:
|
||||
PatchLevelOfDetail(PlugStream *stream);
|
||||
~PatchLevelOfDetail();
|
||||
|
||||
void PlayNote(SourceSet sourceSet);
|
||||
void PlayNote(SourceSet sourceSet, int note);
|
||||
void StopNote(SourceSet sourceSet);
|
||||
|
||||
Logical
|
||||
@@ -93,7 +109,7 @@ public:
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
void
|
||||
SetupPatch(SourceSet sourceSet);
|
||||
SetupPatch(SourceSet sourceSet, int note);
|
||||
|
||||
MIDINRPNValue
|
||||
GetMaxMIDIFilterCutoff()
|
||||
@@ -141,7 +157,7 @@ public:
|
||||
PatchResource(PlugStream *stream);
|
||||
~PatchResource();
|
||||
|
||||
void PlayNote(SourceSet sourceSet);
|
||||
void PlayNote(SourceSet sourceSet, int note);
|
||||
void StopNote(SourceSet sourceSet);
|
||||
|
||||
Logical
|
||||
@@ -166,7 +182,7 @@ public:
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
void
|
||||
SetupPatch(SourceSet sourceSet);
|
||||
SetupPatch(SourceSet sourceSet, int note);
|
||||
|
||||
MIDINRPNValue
|
||||
GetMaxMIDIFilterCutoff();
|
||||
|
||||
@@ -672,6 +672,26 @@ void
|
||||
|
||||
//Feed the buffer with the real PCM sample data
|
||||
alBufferData(g_buffers[bufferInd], format, data, size, wavRate);
|
||||
|
||||
// (task #50, AUDIO_FIDELITY F13) honor the authored loop
|
||||
// REGION -- the EMU8000 looped [dwStartLoop,dwEndLoop], not
|
||||
// the whole sample (MechExplosion's boom carries a ~16 ms
|
||||
// sustain slice that must not replay the full boom).
|
||||
#ifndef AL_LOOP_POINTS_SOFT
|
||||
#define AL_LOOP_POINTS_SOFT 0x2015
|
||||
#endif
|
||||
if (info.loop != ForceStatic && info.loopEnd > info.loopStart)
|
||||
{
|
||||
ALint loop_points[2] = { info.loopStart, info.loopEnd };
|
||||
alGetError();
|
||||
alBufferiv(g_buffers[bufferInd], AL_LOOP_POINTS_SOFT, loop_points);
|
||||
ALenum lpErr = alGetError();
|
||||
if (lpErr != AL_NO_ERROR && getenv("BT_AUDIO_LOG"))
|
||||
DEBUG_STREAM << "[audio] loop-points REJECTED buf" << bufferInd
|
||||
<< " " << info.file << " [" << info.loopStart << ","
|
||||
<< info.loopEnd << "] err=" << lpErr << "\n" << std::flush;
|
||||
}
|
||||
|
||||
if (bufferInd < 512) g_bufferNames[bufferInd] = info.file;
|
||||
if (getenv("BT_AUDIO_LOG") && bufferInd < 3)
|
||||
DEBUG_STREAM << "[audio] loaded buf" << bufferInd << " " << info.file
|
||||
|
||||
@@ -4,7 +4,7 @@ bool PRESET_isImplemented(int bank, int presetn)
|
||||
{
|
||||
PRESETINFO preset = allPresets[bank-1][presetn];
|
||||
|
||||
if (preset.sampleNum <= 0 || preset.sampleNum >= 5)
|
||||
if (preset.sampleNum <= 0 || preset.sampleNum > MAX_PRESET_SAMPLES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -27,15 +27,20 @@ int PRESET_getNumSamples(int bank, int preset)
|
||||
|
||||
SAMPLEINFO PRESET_getSampleInfo(int bank, int preset, int sampleInd)
|
||||
{
|
||||
SAMPLEINFO default;
|
||||
default.chan = SampleChannel::CHANNEL_CENTER;
|
||||
default.file = "";
|
||||
default.implemented = false;
|
||||
default.loop = SampleLoop::LoopAtWill;
|
||||
|
||||
if (sampleInd < 0 || sampleInd >= allPresets[bank-1][preset].sampleNum)
|
||||
{
|
||||
return default;
|
||||
SAMPLEINFO none;
|
||||
none.bufferIndex = -1;
|
||||
none.implemented = false;
|
||||
none.file = "";
|
||||
none.chan = SampleChannel::CHANNEL_CENTER;
|
||||
none.loop = SampleLoop::LoopAtWill;
|
||||
none.keyLo = 0;
|
||||
none.keyHi = 127;
|
||||
none.loopStart = 0;
|
||||
none.loopEnd = 0;
|
||||
none.releaseSec = 0.0f;
|
||||
return none;
|
||||
}
|
||||
|
||||
return allPresets[bank-1][preset].samples[sampleInd];
|
||||
@@ -44,4 +49,4 @@ SAMPLEINFO PRESET_getSampleInfo(int bank, int preset, int sampleInd)
|
||||
void PRESET_setBufferIndex(int bank, int preset, int sampleInd, int index)
|
||||
{
|
||||
allPresets[bank-1][preset].samples[sampleInd].bufferIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user