소스 검색

BeatSequence::reduce() implementiert

Fabian Peter Hammerle 10 년 전
부모
커밋
fe6aa32d72
5개의 변경된 파일117개의 추가작업 그리고 16개의 파일을 삭제
  1. 70 16
      BeatSequence.cpp
  2. 15 0
      BeatSequence.h
  3. 1 0
      tests/CMakeLists.txt
  4. 5 0
      tests/beat-sequence-expansion.cpp
  5. 26 0
      tests/beat-sequence-reducation.cpp

+ 70 - 16
BeatSequence.cpp

@@ -28,35 +28,89 @@ void BeatSequence::expand(BeatIndex factor)
     }
 }
 
-void BeatSequence::print(std::ostream& stream) const
+void BeatSequence::reduce(BeatIndex factor)
+{
+    reduce(factor, 0, 0);
+}
+
+void BeatSequence::reduce(BeatIndex factor, ReducationConflictCallback conflictCallback, void* conflictCallbackData)
 {
-    stream << "beat sequence:\n";
+    if(factor < 1) {
+        throw "factor may not be less than 1."; 
+    }
 
+    if(conflictCallback != 0) {
+        for(BeatIndex beatIndex = 0; beatIndex < size(); beatIndex++) {
+            if(beatIndex % factor != 0 && at(beatIndex).size() > 0) {
+                conflictCallback(*this, factor, beatIndex, conflictCallbackData); 
+            }
+        } 
+    }
+        
     for(BeatIndex beatIndex = 0; beatIndex < size(); beatIndex++) {
+        if(beatIndex % factor != 0 && at(beatIndex).size() > 0) {
+            throw new UnresolvedBeatSequenceReducationConflict(beatIndex);
+        }
+    } 
+
+    BeatIndex targetSize = (size() + factor - 1) / factor;
+    for(BeatIndex targetIndex = 0; targetIndex < targetSize; targetIndex++) {
+        BeatIndex sourceIndex = targetIndex * factor;  
+        at(sourceIndex).swap(at(targetIndex));
+    }
+    resize(targetSize);
+}
+
+void BeatSequence::print(std::ostream& stream) const
+{
+    if(size() == 0) {
+        stream << "beat sequence of length 0\n";
+    } else {
+        stream << "beat sequence:\n";
 
-        std::stringstream beatLabelStream;
-        beatLabelStream << "beat #" << beatIndex << ": ";
-        std::string beatLabel = beatLabelStream.str();
-        stream << beatLabel;
+        for(BeatIndex beatIndex = 0; beatIndex < size(); beatIndex++) {
 
-        std::string spacer(beatLabel.size(), ' ');
+            std::stringstream beatLabelStream;
+            beatLabelStream << "beat #" << beatIndex << ": ";
+            std::string beatLabel = beatLabelStream.str();
+            stream << beatLabel;
 
-        const MessageList& beat = at(beatIndex);
-        if(beat.size() == 0) {
-            stream << "no message" << "\n";
-        } else {
-            for(MessageList::const_iterator msg_it = beat.begin(); msg_it != beat.end(); msg_it++) {
-                if(msg_it != beat.begin()) {
-                    stream << spacer;
+            std::string spacer(beatLabel.size(), ' ');
+
+            const MessageList& beat = at(beatIndex);
+            if(beat.size() == 0) {
+                stream << "no message" << "\n";
+            } else {
+                for(MessageList::const_iterator msg_it = beat.begin(); msg_it != beat.end(); msg_it++) {
+                    if(msg_it != beat.begin()) {
+                        stream << spacer;
+                    }
+                    (*msg_it)->print(stream);
                 }
-                (*msg_it)->print(stream);
             }
-        }
 
+        }
     }
 
     stream << "\n";
     stream.flush();
 }
 
+UnresolvedBeatSequenceReducationConflict::UnresolvedBeatSequenceReducationConflict(BeatSequence::BeatIndex beatIndex)
+    : parent("unresolved beat sequence reducation conflict"), beatIndex(beatIndex)
+{
+}
+
+const char* UnresolvedBeatSequenceReducationConflict::what() const throw()
+{
+    std::stringstream info;
+    info << parent::what() << " at beat #" << getBeatIndex();
+    return info.str().c_str();
+}
+
+BeatSequence::BeatIndex UnresolvedBeatSequenceReducationConflict::getBeatIndex() const
+{
+    return beatIndex;
+}
+
 } // namepsace

+ 15 - 0
BeatSequence.h

@@ -1,6 +1,7 @@
 #pragma once
 #include <vector>
 #include <ostream>
+#include <stdexcept>
 #include "MessageList.h"
 
 namespace midi {
@@ -11,11 +12,25 @@ class BeatSequence : public std::vector<MessageList>
 
 public:
     typedef unsigned int BeatIndex;
+    typedef void (*ReducationConflictCallback)(BeatSequence& sequence, BeatIndex factor, BeatIndex beatIndex, void* data); 
 
     BeatSequence();
     BeatSequence(BeatIndex size);
     void expand(BeatIndex factor);
+    void reduce(BeatIndex factor);
+    void reduce(BeatIndex factor, ReducationConflictCallback conflictCallback, void* conflictCallbackData);
     void print(std::ostream& stream) const;
 };
 
+class UnresolvedBeatSequenceReducationConflict : public std::runtime_error
+{
+    typedef std::runtime_error parent;
+    BeatSequence::BeatIndex beatIndex;
+
+public:
+    UnresolvedBeatSequenceReducationConflict(BeatSequence::BeatIndex beatIndex);
+    virtual const char* what() const throw();
+    BeatSequence::BeatIndex getBeatIndex() const;
+};
+
 } // namespace

+ 1 - 0
tests/CMakeLists.txt

@@ -13,6 +13,7 @@ function(add_test name sources)
 endfunction(add_test)
 
 add_test(beat-sequence-expansion beat-sequence-expansion.cpp)
+add_test(beat-sequence-reducation beat-sequence-reducation.cpp)
 add_test(message-comparison message-comparison.cpp)
 add_test(message-list-find message-list-find.cpp)
 

+ 5 - 0
tests/beat-sequence-expansion.cpp

@@ -15,7 +15,12 @@ int main()
     s.print(std::cout);
 
     s.expand(3);
+    s.print(std::cout);
+
+    s.resize(0);
+    s.print(std::cout);
 
+    s.expand(7);
     s.print(std::cout);
 
     return 0;

+ 26 - 0
tests/beat-sequence-reducation.cpp

@@ -0,0 +1,26 @@
+#include "BeatSequence.h"
+#include <iostream>
+
+using namespace midi;
+
+void conflict(BeatSequence& sequence, BeatSequence::BeatIndex factor, BeatSequence::BeatIndex beatIndex, void* data)
+{
+    std::cout << beatIndex << " " << data << std::endl;
+    sequence[beatIndex].clear();
+}
+
+int main()
+{
+    BeatSequence s(13);
+    for(BeatSequence::BeatIndex b = 0; b < s.size(); b++) {
+        s[b].push_back(std::make_shared<NoteOnMessage>(b, b * 10, 1));
+        s[b].push_back(std::make_shared<NoteOffMessage>(b, b * 10, 2));
+    }
+
+    s.print(std::cout);
+
+    s.reduce(3, conflict, (void*)1234);
+    s.print(std::cout);
+
+    return 0;
+}