Skip to content

Commit 146d45c

Browse files
committed
Fix Android Waveform Dropout: Implement Deep Copy for TrackState and add NULL pointer safety checks
1 parent b2c2642 commit 146d45c

2 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/core/logic/quantize.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <math.h>
44

55
int64_t Quantize_GetNearestBeatMs(TrackState *track, int64_t currentMs) {
6-
if (!track || track->BeatGridCount == 0) return currentMs;
6+
if (!track || track->BeatGridCount == 0 || !track->BeatGrid) return currentMs;
77

88
// Find closest beat in BeatGrid array
99
int64_t closestBeatMs = (int64_t)track->BeatGrid[0].Time;
@@ -24,13 +24,13 @@ int64_t Quantize_GetNearestBeatMs(TrackState *track, int64_t currentMs) {
2424
}
2525

2626
int32_t Quantize_GetPhaseErrorMs(TrackState *track, int64_t currentMs) {
27-
if (!track || track->BeatGridCount == 0) return 0;
27+
if (!track || track->BeatGridCount == 0 || !track->BeatGrid) return 0;
2828
int64_t nearest = Quantize_GetNearestBeatMs(track, currentMs);
2929
return (int32_t)(currentMs - nearest);
3030
}
3131

3232
int32_t Quantize_GetWaitMs(TrackState *track, int64_t currentMs) {
33-
if (!track || track->BeatGridCount == 0) return 0;
33+
if (!track || track->BeatGridCount == 0 || !track->BeatGrid) return 0;
3434

3535
// Look forward for the *next* or *current* beat grid marker
3636
for (int i = 0; i < track->BeatGridCount; i++) {
@@ -42,7 +42,7 @@ int32_t Quantize_GetWaitMs(TrackState *track, int64_t currentMs) {
4242
}
4343

4444
double Quantize_GetBeatDistance(TrackState *track, int64_t currentMs) {
45-
if (!track || track->BeatGridCount < 2) return 0.0;
45+
if (!track || track->BeatGridCount < 2 || !track->BeatGrid) return 0.0;
4646

4747
for (int i = 0; i < track->BeatGridCount - 1; i++) {
4848
if (currentMs >= (int64_t)track->BeatGrid[i].Time && currentMs < (int64_t)track->BeatGrid[i+1].Time) {
@@ -57,7 +57,7 @@ double Quantize_GetBeatDistance(TrackState *track, int64_t currentMs) {
5757
}
5858

5959
int Quantize_GetCurrentBeat(TrackState *track, int64_t currentMs) {
60-
if (!track || track->BeatGridCount == 0) return 1;
60+
if (!track || track->BeatGridCount == 0 || !track->BeatGrid) return 1;
6161
for (int i = 0; i < track->BeatGridCount; i++) {
6262
if ((int64_t)track->BeatGrid[i].Time > currentMs) {
6363
if (i == 0) return track->BeatGrid[0].BeatNumber;
@@ -68,7 +68,7 @@ int Quantize_GetCurrentBeat(TrackState *track, int64_t currentMs) {
6868
}
6969

7070
float Quantize_GetBeatFXLengthMs(TrackState *track, float targetRatio) {
71-
if (!track || track->BeatGridCount < 2) return 0.0f;
71+
if (!track || track->BeatGridCount < 2 || !track->BeatGrid) return 0.0f;
7272

7373
// Calculate average ms per beat from the grid
7474
int count = track->BeatGridCount;

src/ui/browser/browser.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,15 +1082,26 @@ static int Browser_Update(Component *base) {
10821082
newTrack->StaticWaveformType = t->StaticWaveformType;
10831083
memcpy(newTrack->StaticWaveform, t->StaticWaveform,
10841084
t->StaticWaveformLen > 8192 ? 8192 : t->StaticWaveformLen);
1085-
newTrack->DynamicWaveform = t->DynamicWaveform;
1085+
1086+
// DEEP COPY: Isolate dynamic waveform memory per deck
10861087
newTrack->DynamicWaveformLen = t->DynamicWaveformLen;
1088+
if (newTrack->DynamicWaveformLen > 0 && t->DynamicWaveform != NULL) {
1089+
newTrack->DynamicWaveform = (unsigned char*)malloc(newTrack->DynamicWaveformLen);
1090+
if (newTrack->DynamicWaveform) {
1091+
memcpy(newTrack->DynamicWaveform, t->DynamicWaveform, newTrack->DynamicWaveformLen);
1092+
}
1093+
} else {
1094+
newTrack->DynamicWaveform = NULL;
1095+
}
10871096
newTrack->WaveformType = t->WaveformType;
10881097

10891098
// Cues and Beats
10901099
newTrack->BeatGridCount = t->BeatGridCount;
1091-
if (newTrack->BeatGridCount > 0) {
1100+
if (newTrack->BeatGridCount > 0 && t->BeatGrid != NULL) {
10921101
newTrack->BeatGrid = (RBBeat*)malloc(sizeof(RBBeat) * newTrack->BeatGridCount);
1093-
memcpy(newTrack->BeatGrid, t->BeatGrid, sizeof(RBBeat) * newTrack->BeatGridCount);
1102+
if (newTrack->BeatGrid) {
1103+
memcpy(newTrack->BeatGrid, t->BeatGrid, sizeof(RBBeat) * newTrack->BeatGridCount);
1104+
}
10941105
} else {
10951106
newTrack->BeatGrid = NULL;
10961107
}
@@ -1112,9 +1123,12 @@ static int Browser_Update(Component *base) {
11121123
}
11131124

11141125
TrackState *oldTrack = targetDeck->LoadedTrack;
1115-
targetDeck->LoadedTrack = newTrack;
1126+
targetDeck->LoadedTrack = newTrack; // Atomic pointer swap on UI thread
1127+
1128+
// Cleanup old track memory (including buffers)
11161129
if (oldTrack){
11171130
if (oldTrack->BeatGrid != NULL) free(oldTrack->BeatGrid);
1131+
if (oldTrack->DynamicWaveform != NULL) free(oldTrack->DynamicWaveform);
11181132
free(oldTrack);
11191133
}
11201134

@@ -1202,8 +1216,11 @@ static int Browser_Update(Component *base) {
12021216

12031217
TrackState *oldTrack = targetDeck->LoadedTrack;
12041218
targetDeck->LoadedTrack = newTrack;
1205-
if (oldTrack)
1219+
if (oldTrack) {
1220+
if (oldTrack->BeatGrid != NULL) free(oldTrack->BeatGrid);
1221+
if (oldTrack->DynamicWaveform != NULL) free(oldTrack->DynamicWaveform);
12061222
free(oldTrack);
1223+
}
12071224
targetDeck->PositionMs =
12081225
(newTrack->CuesCount > 0) ? newTrack->Cues[0].Start : 0;
12091226
DeckAudio_JumpToMs(&s->AudioPlugin->Decks[loadToDeck],

0 commit comments

Comments
 (0)