Skip to content

Commit 3df08c8

Browse files
committed
feat: 音频文件使用相对路径存储
1 parent 2d44dc3 commit 3df08c8

File tree

3 files changed

+111
-40
lines changed

3 files changed

+111
-40
lines changed

TuneLab/Data/AudioPart.cs

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace TuneLab.Data;
1414
internal class AudioPart : Part, IAudioPart
1515
{
1616
public IActionEvent AudioChanged => mAudioChanged;
17+
public INotifiableProperty<string> BaseDirectory { get; } = new NotifiableProperty<string>(string.Empty);
1718
public override DataString Name { get; }
1819
public override DataStruct<double> Pos { get; }
1920
public override DataStruct<double> Dur { get; }
@@ -27,56 +28,32 @@ public AudioPart(ITrack track, AudioPartInfo info) : base(track)
2728
Dur = new(this);
2829
Path = new(this, string.Empty);
2930
Dur.Modified.Subscribe(mDurationChanged);
30-
Path.Modified.Subscribe(async () =>
31-
{
32-
mAudioData = null;
33-
mWaveforms = [];
34-
mAudioChanged.Invoke();
35-
IAudioData? audioData = null;
36-
Waveform[]? waveforms = null;
37-
await Task.Run(() =>
38-
{
39-
try
40-
{
41-
int samplingRate = AudioEngine.SamplingRate;
42-
var data = AudioUtils.Decode(Path, ref samplingRate);
43-
switch (data.Length)
44-
{
45-
case 1:
46-
audioData = new MonoAudioData(data[0]);
47-
waveforms = [new(data[0])];
48-
break;
49-
case 2:
50-
audioData = new StereoAudioData(data[0], data[1]);
51-
waveforms = [new(data[0]), new(data[1])];
52-
break;
53-
}
54-
}
55-
catch (Exception ex)
56-
{
57-
audioData = null;
58-
waveforms = null;
59-
}
60-
});
61-
62-
if (audioData == null || waveforms == null)
63-
return;
64-
65-
mAudioData = audioData;
66-
mWaveforms = waveforms;
67-
mAudioChanged.Invoke();
31+
Path.Modified.Subscribe(Reload);
32+
BaseDirectory.Modified.Subscribe(() =>
33+
{
34+
if (Path.Value.StartsWith(".."))
35+
Reload();
6836
});
6937
IDataObject<AudioPartInfo>.SetInfo(this, info);
7038
}
7139

7240
public override AudioPartInfo GetInfo()
7341
{
42+
var path = Path.Value;
43+
if (!string.IsNullOrEmpty(BaseDirectory.Value))
44+
{
45+
if (path.StartsWith(BaseDirectory.Value))
46+
{
47+
path = ".." + path[BaseDirectory.Value.Length..];
48+
}
49+
}
50+
7451
return new()
7552
{
7653
Name = Name,
7754
Pos = Pos,
7855
Dur = Dur,
79-
Path = Path
56+
Path = path
8057
};
8158
}
8259

@@ -106,6 +83,51 @@ protected override int SampleCount()
10683
return mAudioData == null ? 0 : Math.Min(base.SampleCount(), mAudioData.Count);
10784
}
10885

86+
async void Reload()
87+
{
88+
mAudioData = null;
89+
mWaveforms = [];
90+
mAudioChanged.Invoke();
91+
IAudioData? audioData = null;
92+
Waveform[]? waveforms = null;
93+
await Task.Run(() =>
94+
{
95+
try
96+
{
97+
string path = Path;
98+
if (path.StartsWith(".."))
99+
{
100+
path = System.IO.Path.Combine(BaseDirectory.Value, path[3..]);
101+
}
102+
int samplingRate = AudioEngine.SamplingRate;
103+
var data = AudioUtils.Decode(path, ref samplingRate);
104+
switch (data.Length)
105+
{
106+
case 1:
107+
audioData = new MonoAudioData(data[0]);
108+
waveforms = [new(data[0])];
109+
break;
110+
case 2:
111+
audioData = new StereoAudioData(data[0], data[1]);
112+
waveforms = [new(data[0]), new(data[1])];
113+
break;
114+
}
115+
}
116+
catch (Exception ex)
117+
{
118+
audioData = null;
119+
waveforms = null;
120+
}
121+
});
122+
123+
if (audioData == null || waveforms == null)
124+
return;
125+
126+
mAudioData = audioData;
127+
mWaveforms = waveforms;
128+
mAudioChanged.Invoke();
129+
}
130+
109131
protected override int SamplingRate => AudioEngine.SamplingRate;
110132
public int ChannelCount => mWaveforms.Length;
111133

TuneLab/Data/IAudioPart.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace TuneLab.Data;
1212
internal interface IAudioPart : IPart, IDataObject<AudioPartInfo>
1313
{
1414
IActionEvent AudioChanged { get; }
15+
INotifiableProperty<string> BaseDirectory { get; }
1516
IDataProperty<string> Path { get; }
1617
int ChannelCount { get; }
1718
Waveform GetWaveform(int channelIndex);

TuneLab/Data/ProjectDocument.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,71 @@ public ProjectDocument()
3131
{
3232
Project?.Attach(this);
3333
});
34+
35+
mProject.When(project => project.Tracks.ItemAdded).Subscribe(track =>
36+
{
37+
var dir = AudioPartBaseDirectory();
38+
if (string.IsNullOrEmpty(dir))
39+
return;
40+
41+
foreach (var audioPart in track.Parts.OfType<IAudioPart>())
42+
{
43+
audioPart.BaseDirectory.Value = dir;
44+
}
45+
});
46+
47+
mProject.When(project => project.Tracks.Any(track => track.Parts.ItemAdded)).Subscribe(part =>
48+
{
49+
if (part is not IAudioPart audioPart)
50+
return;
51+
52+
var dir = AudioPartBaseDirectory();
53+
if (string.IsNullOrEmpty(dir))
54+
return;
55+
56+
audioPart.BaseDirectory.Value = dir;
57+
});
3458
}
3559

3660
public void SetProject(Project project, string path = "")
3761
{
3862
Clear();
39-
SetSavePath(path);
4063
mProject.Set(project);
64+
SetSavePath(path);
4165
}
4266

4367
public void SetSavePath(string path)
4468
{
4569
mPath = path;
70+
ResetAudioPartBaseDirectory();
4671
mName = File.Exists(path) ? new FileInfo(path).Name : "Untitled Project".Tr(TC.Document);
4772
mLastSavedHead = Head;
4873
mProjectNameChanged?.Invoke();
4974
}
5075

76+
string? AudioPartBaseDirectory()
77+
{
78+
if (Project == null)
79+
return null;
80+
81+
return System.IO.Path.GetDirectoryName(mPath);
82+
}
83+
84+
void ResetAudioPartBaseDirectory()
85+
{
86+
if (Project == null)
87+
return;
88+
89+
var dir = AudioPartBaseDirectory();
90+
if (string.IsNullOrEmpty(dir))
91+
return;
92+
93+
foreach (var audioPart in Project.AllAudioParts())
94+
{
95+
audioPart.BaseDirectory.Value = dir;
96+
}
97+
}
98+
5199
string mPath = string.Empty;
52100
string mName = string.Empty;
53101
Head mLastSavedHead;

0 commit comments

Comments
 (0)