@@ -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// ------------------------------------------------
0 commit comments