Skip to content

Commit 8e5c636

Browse files
authored
v2.3.1 (#20)
1 parent 5d82e9d commit 8e5c636

7 files changed

Lines changed: 112 additions & 61 deletions

File tree

Packages/AudioConductor/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## v2.3.1 - 2026/06/11
4+
5+
- Fix Issues
6+
- Fix loop sample range not being applied during track preview playback (regression in v2.0.0)
7+
38
## v2.3.0 - 2026/06/05
49

510
- New Features

Packages/AudioConductor/Editor/Core/Tools/CueSheetEditor/Models/TrackPreviewController.cs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
#nullable enable
66

77
using System;
8+
using AudioConductor.Core;
9+
using AudioConductor.Core.Enums;
810
using AudioConductor.Editor.Core.Tools.Shared;
11+
using UnityEditor;
912
using UnityEngine;
1013
using Object = UnityEngine.Object;
1114

@@ -16,76 +19,80 @@ namespace AudioConductor.Editor.Core.Tools.CueSheetEditor.Models
1619
/// </summary>
1720
internal sealed class TrackPreviewController : IDisposable
1821
{
19-
private AudioSource? _audioSource;
2022
private GameObject? _gameObject;
23+
private AudioClipPlayer? _player;
2124

2225
public TrackPreviewController(AudioClip clip,
2326
int categoryId,
2427
float volume,
2528
float pitch,
2629
bool isLoop,
27-
int startSample)
30+
int startSample,
31+
int loopStartSample,
32+
int endSample)
2833
{
29-
_gameObject = new GameObject("AudioConductor_TrackPreview");
30-
_gameObject.hideFlags = HideFlags.HideAndDontSave;
34+
_gameObject = new GameObject("AudioConductor_TrackPreview")
35+
{
36+
hideFlags = HideFlags.HideAndDontSave
37+
};
3138

32-
_audioSource = _gameObject.AddComponent<AudioSource>();
39+
_player = AudioClipPlayer.Create(_gameObject.transform, HideFlags.HideAndDontSave);
3340

3441
var category = CategoryListRepository.instance.Find(categoryId);
35-
_audioSource.outputAudioMixerGroup = category.audioMixerGroup;
36-
_audioSource.clip = clip;
37-
_audioSource.volume = volume;
38-
_audioSource.pitch = pitch;
39-
_audioSource.loop = isLoop;
40-
_audioSource.timeSamples = startSample;
41-
_audioSource.playOnAwake = false;
42+
_player.Setup(category.audioMixerGroup, clip, categoryId, volume, pitch, isLoop,
43+
startSample, loopStartSample, endSample);
44+
45+
EditorApplication.update += OnEditorUpdate;
4246
}
4347

44-
public bool IsPlaying => _audioSource != null && _audioSource.isPlaying;
48+
public bool IsPlaying => _player is { State: PlayerState.Playing };
4549

4650
public void Dispose()
4751
{
52+
EditorApplication.update -= OnEditorUpdate;
53+
4854
if (_gameObject != null)
4955
{
5056
Object.DestroyImmediate(_gameObject);
5157
_gameObject = null;
52-
_audioSource = null;
5358
}
59+
60+
_player = null;
5461
}
5562

5663
public void Play()
5764
{
58-
if (_audioSource != null)
59-
_audioSource.Play();
65+
_player?.Play();
6066
}
6167

6268
public void Stop()
6369
{
64-
if (_audioSource != null)
65-
_audioSource.Stop();
70+
_player?.Stop();
6671
}
6772

6873
public void Pause()
6974
{
70-
if (_audioSource != null)
71-
_audioSource.Pause();
75+
_player?.Pause();
7276
}
7377

7478
public void UnPause()
7579
{
76-
if (_audioSource != null)
77-
_audioSource.UnPause();
80+
_player?.Resume();
7881
}
7982

8083
public void SetCurrentSample(int sample)
8184
{
82-
if (_audioSource != null)
83-
_audioSource.timeSamples = sample;
85+
_player?.SetCurrentSample(sample);
8486
}
8587

8688
public int GetCurrentSample()
8789
{
88-
return _audioSource != null ? _audioSource.timeSamples : 0;
90+
return _player?.GetCurrentSample() ?? 0;
91+
}
92+
93+
private void OnEditorUpdate()
94+
{
95+
_player?.ManualUpdate(0f);
8996
}
9097
}
9198
}

Packages/AudioConductor/Editor/Core/Tools/CueSheetEditor/Models/TrackPreviewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public TrackPreviewModel(ItemTrack item)
3838
var startSample = _track.startSample;
3939

4040
var controller = new TrackPreviewController(clip, _cue.categoryId, volume, pitch, isLoop,
41-
sample ?? startSample);
41+
sample ?? startSample, _track.loopStartSample, _track.endSample);
4242
controller.Play();
4343
return controller;
4444
}

Packages/AudioConductor/Runtime/Core/AudioClipPlayer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,11 @@ public void ManualUpdate(float _)
322322
}
323323
}
324324

325-
internal static AudioClipPlayer Create(Transform parent)
325+
internal static AudioClipPlayer Create(Transform parent, HideFlags hideFlags = HideFlags.None)
326326
{
327327
var root = new GameObject(nameof(AudioClipPlayer));
328328
root.transform.SetParent(parent);
329+
root.hideFlags = hideFlags;
329330
var sources = new IAudioSourceWrapper[SourceNum];
330331
for (var i = 0; i < SourceNum; i++)
331332
sources[i] = new AudioSourceWrapper(root.AddComponent<AudioSource>());

Packages/AudioConductor/Tests/Editor/Core/AudioClipPlayerTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ public void TearDown()
3939
private AudioClipPlayer _player = null!;
4040
private AudioClip _clip = null!;
4141

42-
private void SetupPlayer(float volume = 1f, float pitch = 1f, bool isLoop = false, int endSample = 0)
42+
private void SetupPlayer(float volume = 1f, float pitch = 1f, bool isLoop = false,
43+
int loopStartSample = 0, int endSample = 0)
4344
{
44-
_player.Setup(null, _clip, 0, volume, pitch, isLoop, 0, 0, endSample);
45+
_player.Setup(null, _clip, 0, volume, pitch, isLoop, 0, loopStartSample, endSample);
4546
}
4647

4748
// --- Volume (5-factor multiplication) ---
@@ -381,6 +382,20 @@ public void ManualUpdate_Loop_WithValidEndSample_TriggersLoopOnTime()
381382
Assert.That(_source1.IsPlaying, Is.True);
382383
}
383384

385+
[Test]
386+
public void ManualUpdate_Loop_WithNonZeroLoopStartSample_StartsNextLoopAtLoopStartSample()
387+
{
388+
const int loopStartSample = 1000;
389+
_clock.DspTime = 0.0;
390+
SetupPlayer(isLoop: true, loopStartSample: loopStartSample, endSample: _clip.samples);
391+
_player.Play();
392+
393+
_clock.DspTime = 0.15;
394+
_player.ManualUpdate(0.1f);
395+
396+
Assert.That(_source1.TimeSamples, Is.EqualTo(loopStartSample));
397+
}
398+
384399
// --- Restart ---
385400

386401
[Test]

Packages/AudioConductor/Tests/Editor/Core/Tools/CueSheetEditor/Models/TrackPreviewControllerTests.cs

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,84 +25,107 @@ public void TearDown()
2525
Object.DestroyImmediate(_clip);
2626
}
2727

28-
[Test]
29-
public void IsPlaying_InitialState_ReturnsFalse()
28+
[TestCase(false, 0, 0, 0)]
29+
[TestCase(true, 0, 1000, 40000)]
30+
public void IsPlaying_InitialState_ReturnsFalse(bool isLoop, int startSample, int loopStartSample,
31+
int endSample)
3032
{
31-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
33+
using var controller =
34+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
3235
Assert.That(controller.IsPlaying, Is.False);
3336
}
3437

35-
[Test]
36-
public void IsPlaying_AfterDispose_ReturnsFalse()
38+
[TestCase(false, 0, 0, 0)]
39+
[TestCase(true, 0, 1000, 40000)]
40+
public void IsPlaying_AfterDispose_ReturnsFalse(bool isLoop, int startSample, int loopStartSample,
41+
int endSample)
3742
{
38-
var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
43+
var controller =
44+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
3945
controller.Dispose();
4046
Assert.That(controller.IsPlaying, Is.False);
4147
}
4248

43-
[Test]
44-
public void GetCurrentSample_BeforePlay_ReturnsZero()
49+
[TestCase(false, 0, 0, 0)]
50+
[TestCase(true, 0, 1000, 40000)]
51+
public void GetCurrentSample_BeforePlay_ReturnsZero(bool isLoop, int startSample, int loopStartSample,
52+
int endSample)
4553
{
46-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
54+
using var controller =
55+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
4756
Assert.That(controller.GetCurrentSample(), Is.EqualTo(0));
4857
}
4958

50-
[Test]
51-
public void Dispose_CalledTwice_DoesNotThrow()
59+
[TestCase(false, 0, 0, 0)]
60+
[TestCase(true, 0, 1000, 40000)]
61+
public void Dispose_CalledTwice_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
5262
{
53-
var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
63+
var controller =
64+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
5465
controller.Dispose();
5566
Assert.DoesNotThrow(() => controller.Dispose());
5667
}
5768

58-
[Test]
59-
public void Play_DoesNotThrow()
69+
[TestCase(false, 0, 0, 0)]
70+
[TestCase(true, 0, 1000, 40000)]
71+
public void Play_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
6072
{
61-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
73+
using var controller =
74+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
6275
Assert.DoesNotThrow(() => controller.Play());
6376
}
6477

65-
[Test]
66-
public void Stop_DoesNotThrow()
78+
[TestCase(false, 0, 0, 0)]
79+
[TestCase(true, 0, 1000, 40000)]
80+
public void Stop_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
6781
{
68-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
82+
using var controller =
83+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
6984
Assert.DoesNotThrow(() => controller.Stop());
7085
}
7186

72-
[Test]
73-
public void Pause_DoesNotThrow()
87+
[TestCase(false, 0, 0, 0)]
88+
[TestCase(true, 0, 1000, 40000)]
89+
public void Pause_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
7490
{
75-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
91+
using var controller =
92+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
7693
Assert.DoesNotThrow(() => controller.Pause());
7794
}
7895

79-
[Test]
80-
public void UnPause_DoesNotThrow()
96+
[TestCase(false, 0, 0, 0)]
97+
[TestCase(true, 0, 1000, 40000)]
98+
public void UnPause_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
8199
{
82-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
100+
using var controller =
101+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
83102
Assert.DoesNotThrow(() => controller.UnPause());
84103
}
85104

86105
[Test]
87106
public void SetCurrentSample_ThenGetCurrentSample_ReturnsSetValue()
88107
{
89-
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
108+
using var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0, 0, 0);
90109
controller.SetCurrentSample(100);
91110
Assert.That(controller.GetCurrentSample(), Is.EqualTo(100));
92111
}
93112

94-
[Test]
95-
public void Play_AfterDispose_DoesNotThrow()
113+
[TestCase(false, 0, 0, 0)]
114+
[TestCase(true, 0, 1000, 40000)]
115+
public void Play_AfterDispose_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
96116
{
97-
var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
117+
var controller =
118+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
98119
controller.Dispose();
99120
Assert.DoesNotThrow(() => controller.Play());
100121
}
101122

102-
[Test]
103-
public void Stop_AfterDispose_DoesNotThrow()
123+
[TestCase(false, 0, 0, 0)]
124+
[TestCase(true, 0, 1000, 40000)]
125+
public void Stop_AfterDispose_DoesNotThrow(bool isLoop, int startSample, int loopStartSample, int endSample)
104126
{
105-
var controller = new TrackPreviewController(_clip, -1, 1f, 1f, false, 0);
127+
var controller =
128+
new TrackPreviewController(_clip, -1, 1f, 1f, isLoop, startSample, loopStartSample, endSample);
106129
controller.Dispose();
107130
Assert.DoesNotThrow(() => controller.Stop());
108131
}

Packages/AudioConductor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jp.co.cyberagent.audioconductor",
3-
"version": "2.3.0",
3+
"version": "2.3.1",
44
"displayName": "Audio Conductor",
55
"unity": "2022.3",
66
"license": "MIT",

0 commit comments

Comments
 (0)