Skip to content

Commit ab8e071

Browse files
committed
Fix preview music not processed correctly
1 parent 8553392 commit ab8e071

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

source/funkin/play/PlayState.hx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,9 +1600,8 @@ class PlayState extends MusicBeatSubState
16001600
// Resume vwooshTimer
16011601
if (!vwooshTimer.finished) vwooshTimer.active = true;
16021602

1603-
// The logic here is that if this sound doesn't auto-destroy
1604-
// then it's gonna be reused somewhere, so we just stop it instead.
1605-
forEachPausedSound(s -> needsReset ? (s.autoDestroy ? s.destroy() : s.stop()) : s.resume());
1603+
// Stopping a sound will kills itself anyway if s.autoDestroy is true.
1604+
forEachPausedSound(s -> needsReset ? s.stop() : s.resume());
16061605

16071606
// Resume camera tweens if we paused any.
16081607
for (camTween in cameraTweensPausedBySubState)

source/funkin/ui/freeplay/FreeplayState.hx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3001,7 +3001,7 @@ class FreeplayState extends MusicBeatSubState
30013001
}
30023002

30033003
if (previewMusicData == null) previewMusicData = new PreviewMusicData();
3004-
previewMusicData.setAssetPath(Paths.inst(previewSong.id, instSuffix), songDifficulty?.previewStart, songDifficulty?.previewEnd, true,
3004+
previewMusicData.setAssetPath(Paths.inst(previewSong.id, instSuffix), songDifficulty?.previewStart, songDifficulty?.previewEnd, null,
30053005
function(musicData:PreviewMusicData)
30063006
{
30073007
// Check again if it's still selected.

source/funkin/ui/freeplay/components/PreviewMusicData.hx

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import openfl.utils.Assets;
77
import flixel.sound.FlxSoundData;
88

99
#if native
10+
import sys.thread.Mutex;
11+
1012
import haxe.Int64;
1113
import lime.media.AudioDecoder;
1214
import lime.utils.ArrayBuffer;
@@ -48,7 +50,7 @@ class PreviewMusicData extends FlxSoundData
4850
#end
4951
}
5052

51-
public function setAssetPath(path:String, startTime = 0, endTime = 15000, stream = true, ?onLoad:PreviewMusicData->Void):Void
53+
public function setAssetPath(path:String, startTime = 0, endTime = 15000, ?stream:Bool, ?onLoad:PreviewMusicData->Void):Void
5254
{
5355
var cacheName = #if web 'PreviewMusicDataWeb-$path' #else 'PreviewMusicData-$path-$startTime-$endTime' #end;
5456

@@ -73,20 +75,32 @@ class PreviewMusicData extends FlxSoundData
7375

7476
audioDecoderProcess.resetDecoder(decoder, startTime, endTime);
7577

76-
if (stream)
78+
if (stream == null) stream = FlxSoundData.allowStreaming && endTime >= FlxSoundData.streamMinimumLength;
79+
if (stream && decoder.seekable())
7780
{
78-
audioBufferProcess.bitsPerSample = audioDecoderProcess.decoder.bitsPerSample;
79-
audioBufferProcess.channels = audioDecoderProcess.decoder.channels;
80-
audioBufferProcess.sampleRate = audioDecoderProcess.decoder.sampleRate;
81+
audioBufferProcess.bitsPerSample = audioDecoderProcess.bitsPerSample;
82+
audioBufferProcess.channels = audioDecoderProcess.channels;
83+
audioBufferProcess.sampleRate = audioDecoderProcess.sampleRate;
8184
buffer = audioBufferProcess;
85+
86+
if (onLoad != null) onLoad(this);
8287
}
8388
else
8489
{
85-
buffer = AudioBuffer.fromDecoder(audioDecoderProcess, false, false);
90+
buffer = new AudioBuffer();
91+
buffer.decoder = audioDecoderProcess;
92+
buffer.loadAsync((_) -> {
93+
buffer.decoder = null;
94+
95+
//var output = sys.io.File.write("../../../../tempPartial.dat", true);
96+
//output.writeBytes(buffer.data.buffer, 0, buffer.data.byteLength);
97+
//output.close();
98+
99+
if (onLoad != null) onLoad(this);
100+
});
101+
86102
FlxSoundData.fromAudioBuffer(buffer, cacheName, true);
87103
}
88-
89-
if (onLoad != null) onLoad(this);
90104
#elseif web
91105
// In web, use FlxPartialSound...
92106
// hardcode it to use percentage from 0 to 0.2
@@ -95,11 +109,12 @@ class PreviewMusicData extends FlxSoundData
95109
var promise = FlxPartialSound.partialLoadFromFile(Paths.stripLibrary(path), 0, 0.2);
96110
if (promise == null) return;
97111

112+
@:privateAccess
113+
var soundData = FlxSoundData.createSoundData(null, cacheName, true);
114+
98115
promise.future.onComplete(function(partialSound)
99116
@:privateAccess {
100-
buffer = @:privateAccess partialSound.__buffer;
101-
FlxSoundData.fromAudioBuffer(buffer, cacheName, true);
102-
117+
soundData.buffer = buffer = partialSound.__buffer;
103118
if (buffer.__srcAudioBuffer != null)
104119
{
105120
processFading(buffer.__srcAudioBuffer);
@@ -174,15 +189,19 @@ private class PreviewMusicDecoder extends AudioDecoder
174189
var bufferInt8View:Int8Array;
175190
var bufferInt16View:Int16Array;
176191
var bufferInt32View:Int32Array;
192+
var mutex:Mutex;
177193

178194
public function new(parent:PreviewMusicData)
179195
{
180196
super();
181197
this.parent = parent;
198+
mutex = new Mutex();
182199
}
183200

184201
public function resetDecoder(decoder:AudioDecoder, startTime:Float, endTime:Float):Void
185202
{
203+
mutex.acquire();
204+
186205
var oldDecoder = this.decoder;
187206
if (oldDecoder != null) oldDecoder.dispose();
188207

@@ -213,6 +232,8 @@ private class PreviewMusicDecoder extends AudioDecoder
213232

214233
rewind();
215234
}
235+
236+
mutex.release();
216237
}
217238

218239
override function clone():PreviewMusicDecoder
@@ -229,6 +250,8 @@ private class PreviewMusicDecoder extends AudioDecoder
229250
{
230251
if (decoder == null) return 0;
231252

253+
mutex.acquire();
254+
232255
var currentSampleOffset = decoder.tell() - startSamples;
233256
var remainingBytes = (endSamples - currentSampleOffset) * channels * byteRate;
234257

@@ -244,32 +267,43 @@ private class PreviewMusicDecoder extends AudioDecoder
244267
eof = decoder.eof;
245268
}
246269

247-
if (byteRate == 3) return result;
270+
if (byteRate == 3)
271+
{
272+
mutex.release();
273+
return result;
274+
}
248275

276+
// Fading processing
249277
if (bufferView.buffer != buffer) bufferView.initBuffer(buffer);
250278

251-
var i = 0;
252-
var channel = 0;
253-
var length = Std.int(result / byteRate);
254-
while (i < length)
279+
pos = Std.int(pos / byteRate);
280+
len = pos + Std.int(result / byteRate);
281+
var channel = 0, b:Int;
282+
while (pos < len)
255283
{
256284
if (currentSampleOffset < fadeStartSamples)
257285
{
258286
switch (byteRate)
259287
{
260-
case 1: bufferInt8View[i] = Std.int(bufferInt8View[i] * currentSampleOffset.low / fadeStartSamples.low);
261-
case 2: bufferInt16View[i] = Std.int(bufferInt16View[i] * currentSampleOffset.low / fadeStartSamples.low);
262-
case 4: bufferInt32View[i] = Std.int(bufferInt32View[i] * currentSampleOffset.low / fadeStartSamples.low);
288+
case 1:
289+
bufferInt8View[pos] = Std.int(bufferInt8View[pos] * (currentSampleOffset.low / fadeStartSamples.low).clamp(0, 1));
290+
case 2:
291+
bufferInt16View[pos] = Std.int(bufferInt16View[pos] * (currentSampleOffset.low / fadeStartSamples.low).clamp(0, 1));
292+
case 4:
293+
bufferInt32View[pos] = Std.int(bufferInt32View[pos] * (currentSampleOffset.low / fadeStartSamples.low).clamp(0, 1));
263294
default:
264295
}
265296
}
266297
else if (currentSampleOffset > fadeEndStartSampleOffset)
267298
{
268299
switch (byteRate)
269300
{
270-
case 1: bufferInt8View[i] = Std.int(bufferInt8View[i] * (fadeEndEndSampleOffset - currentSampleOffset).low / fadeStartSamples.low);
271-
case 2: bufferInt16View[i] = Std.int(bufferInt16View[i] * (fadeEndEndSampleOffset - currentSampleOffset).low / fadeStartSamples.low);
272-
case 4: bufferInt32View[i] = Std.int(bufferInt32View[i] * (fadeEndEndSampleOffset - currentSampleOffset).low / fadeStartSamples.low);
301+
case 1:
302+
bufferInt8View[pos] = Std.int(bufferInt8View[pos] * ((fadeEndEndSampleOffset - currentSampleOffset).low / fadeEndSamples.low).clamp(0, 1));
303+
case 2:
304+
bufferInt16View[pos] = Std.int(bufferInt16View[pos] * ((fadeEndEndSampleOffset - currentSampleOffset).low / fadeEndSamples.low).clamp(0, 1));
305+
case 4:
306+
bufferInt32View[pos] = Std.int(bufferInt32View[pos] * ((fadeEndEndSampleOffset - currentSampleOffset).low / fadeEndSamples.low).clamp(0, 1));
273307
default:
274308
}
275309
}
@@ -279,9 +313,11 @@ private class PreviewMusicDecoder extends AudioDecoder
279313
channel = 0;
280314
currentSampleOffset++;
281315
}
282-
i++;
316+
pos++;
283317
}
284318

319+
mutex.release();
320+
285321
return result;
286322
}
287323

0 commit comments

Comments
 (0)