Skip to content

Commit e5803f6

Browse files
committed
rotated files are now cached
1 parent df7b2b8 commit e5803f6

3 files changed

Lines changed: 151 additions & 35 deletions

File tree

include/Kaixo/SpectralRotator/Processing/FileHandler.hpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,32 @@ namespace Kaixo::Processing {
3636

3737
void waitForReadingToFinish();
3838
FileLoadStatus open(std::filesystem::path path, std::size_t bitDepth = 16, double sampleRate = 48000);
39-
void rotate(FileHandler& destination, Rotation direction, const AudioBuffer& originalBuffer = {});
40-
void writeBuffer(AudioBuffer&& other, bool lock = true);
39+
void rotate(Rotation direction, const AudioBuffer& originalBuffer = {});
4140

4241
float loadingProgress();
4342

4443
// ------------------------------------------------
4544

46-
std::size_t size() const { return file.buffer.size(); }
45+
std::size_t size();
4746

4847
// ------------------------------------------------
4948

50-
AudioFile file{};
49+
constexpr static int d000f = 0;
50+
constexpr static int d090f = 1;
51+
constexpr static int d180f = 2;
52+
constexpr static int d270f = 3;
53+
constexpr static int d000r = 4;
54+
constexpr static int d090r = 5;
55+
constexpr static int d180r = 6;
56+
constexpr static int d270r = 7;
57+
58+
std::atomic_int currentRotation = d000f;
59+
std::map<int, AudioFile> rotations;
60+
61+
AudioFile* file();
62+
63+
int nextRotation(Rotation direction);
64+
std::pair<int, Rotation> getMostEfficientRotationTo(Rotation direction);
5165

5266
// ------------------------------------------------
5367

source/Kaixo/SpectralRotator/Processing/FileHandler.cpp

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ namespace Kaixo::Processing {
1919

2020
// Do not read file while modifying. The modifying functions will
2121
// wait for this function to finish reading.
22-
if (!playing || modifyingFile) {
22+
if (!playing || modifyingFile || file() == nullptr) {
2323
output = 0;
2424
readingFile = false;
2525
return;
2626
}
2727

28-
resampler.samplerate.in = file.buffer.sampleRate;
28+
resampler.samplerate.in = file()->buffer.sampleRate;
2929
resampler.samplerate.out = sampleRate();
30-
output = resampler.generate(file.buffer);
30+
output = resampler.generate(file()->buffer);
3131

3232
if (resampler.eof()) {
3333
playing = false;
@@ -50,13 +50,13 @@ namespace Kaixo::Processing {
5050
}
5151

5252
void FileHandler::seek(float position) {
53-
seekPosition = position * file.buffer.size();
53+
seekPosition = position * size();
5454
newSeekPosition = true;
5555
}
5656

5757
float FileHandler::position() {
58-
if (file.buffer.size() == 0) return 0;
59-
return static_cast<float>(resampler.position()) / file.buffer.size();
58+
if (size() == 0) return 0;
59+
return static_cast<float>(resampler.position()) / size();
6060
}
6161

6262
// ------------------------------------------------
@@ -73,33 +73,30 @@ namespace Kaixo::Processing {
7373

7474
modifyingFile = true;
7575
waitForReadingToFinish();
76-
FileLoadStatus result = file.open(path, bitDepth, sampleRate);
76+
rotations.clear();
77+
currentRotation = d000f;
78+
FileLoadStatus result = rotations[d000f].open(path, bitDepth, sampleRate);
79+
if (result != FileLoadStatus::Success) rotations.clear();
7780
modifyingFile = false;
7881
return result;
7982
}
8083

81-
void FileHandler::rotate(FileHandler& destination, Rotation direction, const AudioBuffer& originalBuffer) {
84+
void FileHandler::rotate(Rotation direction, const AudioBuffer& originalBuffer) {
8285
std::lock_guard lock{ fileMutex };
8386

8487
modifyingFile = true;
8588
waitForReadingToFinish();
8689

87-
bool inPlace = destination.file.buffer.data() == file.buffer.data();
88-
destination.writeBuffer(rotator.rotate(file.buffer, direction, originalBuffer), /* Only lock when not in-place*/ !inPlace);
90+
int rotated = nextRotation(direction);
8991

90-
modifyingFile = false;
91-
}
92-
93-
void FileHandler::writeBuffer(AudioBuffer&& other, bool doLock) {
94-
std::unique_lock lock{ fileMutex, std::defer_lock_t{} };
95-
if (doLock) lock.lock();
96-
97-
modifyingFile = true;
98-
waitForReadingToFinish();
92+
if (!rotations.contains(rotated)) {
93+
auto [from, dir] = getMostEfficientRotationTo(direction);
94+
rotations[rotated].buffer = std::move(rotator.rotate(rotations[from].buffer, dir, originalBuffer));
95+
rotations[rotated].path = ""; // Buffer changed, so file path no longer valid
96+
rotations[rotated].changed = true; // Signal that it has changed
97+
}
9998

100-
file.buffer = std::move(other);
101-
file.path = ""; // Buffer changed, so file path no longer valid
102-
file.changed = true; // Signal that it has changed
99+
currentRotation = rotated;
103100

104101
modifyingFile = false;
105102
}
@@ -114,6 +111,107 @@ namespace Kaixo::Processing {
114111

115112
// ------------------------------------------------
116113

114+
std::size_t FileHandler::size() {
115+
if (auto curFile = file()) return curFile->buffer.size();
116+
return 0;
117+
}
118+
119+
// ------------------------------------------------
120+
121+
AudioFile* FileHandler::file() { return rotations.contains(currentRotation) ? &rotations[currentRotation] : nullptr; }
122+
123+
int FileHandler::nextRotation(Rotation direction) {
124+
switch (direction) {
125+
case Rotation::Flip:
126+
switch (currentRotation) {
127+
case d000f: return d180r;
128+
case d090f: return d270r;
129+
case d180f: return d000r;
130+
case d270f: return d090r;
131+
case d000r: return d180f;
132+
case d090r: return d270f;
133+
case d180r: return d000f;
134+
case d270r: return d090f;
135+
}
136+
break;
137+
case Rotation::Reverse:
138+
switch (currentRotation) {
139+
case d000f: return d000r;
140+
case d090f: return d090r;
141+
case d180f: return d180r;
142+
case d270f: return d270r;
143+
case d000r: return d000f;
144+
case d090r: return d090f;
145+
case d180r: return d180f;
146+
case d270r: return d270f;
147+
}
148+
break;
149+
case Rotation::Rotate90:
150+
switch (currentRotation) {
151+
case d000f: return d090f;
152+
case d090f: return d180f;
153+
case d180f: return d270f;
154+
case d270f: return d000f;
155+
case d000r: return d270r;
156+
case d090r: return d000r;
157+
case d180r: return d090r;
158+
case d270r: return d180r;
159+
}
160+
break;
161+
case Rotation::Rotate270:
162+
switch (currentRotation) {
163+
case d000f: return d270f;
164+
case d090f: return d000f;
165+
case d180f: return d090f;
166+
case d270f: return d180f;
167+
case d000r: return d090r;
168+
case d090r: return d180r;
169+
case d180r: return d270r;
170+
case d270r: return d000r;
171+
}
172+
break;
173+
}
174+
175+
return currentRotation;
176+
}
177+
178+
std::pair<int, Rotation> FileHandler::getMostEfficientRotationTo(Rotation direction) {
179+
int goingTo = nextRotation(direction);
180+
switch (direction) {
181+
case Rotation::Rotate270:
182+
case Rotation::Rotate90:
183+
switch (goingTo) {
184+
case d000f: return rotations.contains(d180r) ? std::pair{ d180r, Rotation::Flip }
185+
: rotations.contains(d000r) ? std::pair{ d000r, Rotation::Reverse }
186+
: std::pair{ (int)currentRotation, direction };
187+
case d090f: return rotations.contains(d270r) ? std::pair{ d270r, Rotation::Flip }
188+
: rotations.contains(d090r) ? std::pair{ d090r, Rotation::Reverse }
189+
: std::pair{ (int)currentRotation, direction };
190+
case d180f: return rotations.contains(d000r) ? std::pair{ d000r, Rotation::Flip }
191+
: rotations.contains(d180r) ? std::pair{ d180r, Rotation::Reverse }
192+
: std::pair{ (int)currentRotation, direction };
193+
case d270f: return rotations.contains(d090r) ? std::pair{ d090r, Rotation::Flip }
194+
: rotations.contains(d270r) ? std::pair{ d270r, Rotation::Reverse }
195+
: std::pair{ (int)currentRotation, direction };
196+
case d000r: return rotations.contains(d180f) ? std::pair{ d180f, Rotation::Flip }
197+
: rotations.contains(d000f) ? std::pair{ d000f, Rotation::Reverse }
198+
: std::pair{ (int)currentRotation, direction };
199+
case d090r: return rotations.contains(d270f) ? std::pair{ d270f, Rotation::Flip }
200+
: rotations.contains(d090f) ? std::pair{ d090f, Rotation::Reverse }
201+
: std::pair{ (int)currentRotation, direction };
202+
case d180r: return rotations.contains(d000f) ? std::pair{ d000f, Rotation::Flip }
203+
: rotations.contains(d180f) ? std::pair{ d180f, Rotation::Reverse }
204+
: std::pair{ (int)currentRotation, direction };
205+
case d270r: return rotations.contains(d090f) ? std::pair{ d090f, Rotation::Flip }
206+
: rotations.contains(d270f) ? std::pair{ d270f, Rotation::Reverse }
207+
: std::pair{ (int)currentRotation, direction };
208+
}
209+
}
210+
return { (int)currentRotation, direction };
211+
}
212+
213+
// ------------------------------------------------
214+
117215
}
118216

119217
// ------------------------------------------------

source/Kaixo/SpectralRotator/Processing/Interfaces.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ namespace Kaixo::Processing {
1818

1919
switch (settings.index) {
2020
case 1:
21-
processor.rotatedFile.file.save(processor.inputFile.file.path.stem().string());
21+
if (processor.rotatedFile.file() == nullptr) return;
22+
processor.rotatedFile.file()->save(processor.inputFile.file()->path.stem().string());
2223
break;
2324
}
2425
}
@@ -28,11 +29,12 @@ namespace Kaixo::Processing {
2829
auto& processor = self<SpectralRotatorProcessor>();
2930

3031
switch (index) {
31-
case 0:
32-
processor.inputFile.rotate(processor.rotatedFile, direction);
33-
break;
3432
case 1:
35-
processor.rotatedFile.rotate(processor.rotatedFile, direction, processor.inputFile.file.buffer);
33+
if (processor.inputFile.file() == nullptr) {
34+
processor.rotatedFile.rotate(direction);
35+
} else {
36+
processor.rotatedFile.rotate(direction, processor.inputFile.file()->buffer);
37+
}
3638
break;
3739
}
3840
});
@@ -111,8 +113,8 @@ namespace Kaixo::Processing {
111113
auto& processor = self<SpectralRotatorProcessor>();
112114

113115
switch (settings.index) {
114-
case 0: return processor.inputFile.file.path;
115-
case 1: return processor.rotatedFile.file.path;
116+
case 0: return processor.inputFile.file() ? processor.inputFile.file()->path : "";
117+
case 1: return processor.rotatedFile.file() ? processor.rotatedFile.file()->path : "";
116118
}
117119

118120
return {};
@@ -126,12 +128,14 @@ namespace Kaixo::Processing {
126128
switch (settings.index) {
127129
case 0: {
128130
std::lock_guard lock{ processor.inputFile.fileMutex };
129-
return AudioBufferSpectralInformation::analyze(processor.inputFile.file.buffer, fftSize, horizontalResolution, blockSize, progress);
131+
if (processor.inputFile.file() == nullptr) return {};
132+
return AudioBufferSpectralInformation::analyze(processor.inputFile.file()->buffer, fftSize, horizontalResolution, blockSize, progress);
130133
break;
131134
}
132135
case 1: {
133136
std::lock_guard lock{ processor.rotatedFile.fileMutex };
134-
return AudioBufferSpectralInformation::analyze(processor.rotatedFile.file.buffer, fftSize, horizontalResolution, blockSize, progress);
137+
if (processor.rotatedFile.file() == nullptr) return {};
138+
return AudioBufferSpectralInformation::analyze(processor.rotatedFile.file()->buffer, fftSize, horizontalResolution, blockSize, progress);
135139
break;
136140
}
137141
}

0 commit comments

Comments
 (0)