Big Mouth Billy Bass automation library
Revision 4:f009306756b3, committed 2013-06-18
- Comitter:
- bikeNomad
- Date:
- Tue Jun 18 14:10:34 2013 +0000
- Parent:
- 3:6c91a6232c4a
- Child:
- 5:869b3711bdb3
- Commit message:
- working. re-used one Song for memory reduction.
Changed in this revision
--- a/action.hpp Tue Jun 18 13:11:07 2013 +0000
+++ b/action.hpp Tue Jun 18 14:10:34 2013 +0000
@@ -15,12 +15,17 @@
DigitalOut *_out = 0,
char const *_outName = 0)
: actionTime(_time), desiredState(_state)
- , output(_out), outputName(_outName) {
+ , output(_out) {
}
bool operator < (Action const &other) const {
return actionTime < other.actionTime;
}
+
+ // return <0 if *p1 is before *p2
+ static int compare(const void* p1, const void* p2) {
+ return static_cast<Action const *>(p1)->actionTime - static_cast<Action const *>(p2)->actionTime;
+ }
bool isValid() const {
return actionTime >= 0.0 && output != 0;
@@ -29,18 +34,22 @@
void act() {
output->write(desiredState ? 1 : 0);
}
-
+
bool actIfPast(float _now) {
if (_now >= actionTime) {
act();
return true;
} else return false;
}
+ void set(float _time, int _state, DigitalOut* _out) {
+ actionTime = _time;
+ desiredState = _state;
+ output = _out;
+ }
float actionTime;
- bool desiredState;
+ int desiredState;
DigitalOut *output;
- char const *outputName;
};
#endif
--- a/billybass.cpp Tue Jun 18 13:11:07 2013 +0000
+++ b/billybass.cpp Tue Jun 18 14:10:34 2013 +0000
@@ -16,15 +16,21 @@
if (!strcmp(_outputName, mouthName)) {
output = &mouth;
if (_pName) *_pName = mouthName;
- }
- else if (!strcmp(_outputName, "head") || !strcmp(_outputName, bodyName)) {
+ } else if (!strcmp(_outputName, "head") || !strcmp(_outputName, bodyName)) {
output = &body;
if (_pName) *_pName = bodyName;
- }
- else if (!strcmp(_outputName, tailName)) {
+ } else if (!strcmp(_outputName, tailName)) {
output = &tail;
if (_pName) *_pName = tailName;
}
return output;
}
+
+char const *BillyBass::outputName(DigitalOut const *out) const
+{
+ if (out == &tail) return tailName;
+ else if (out == &body) return bodyName;
+ else if (out == &mouth) return mouthName;
+ else return "unknown";
+}
--- a/billybass.hpp Tue Jun 18 13:11:07 2013 +0000
+++ b/billybass.hpp Tue Jun 18 14:10:34 2013 +0000
@@ -42,6 +42,7 @@
mouth.write(offState());
body.write(offState());
}
+ char const * outputName(DigitalOut const *out) const;
protected:
static BillyBass* fish[ MAX_FISH ];
--- a/player.hpp Tue Jun 18 13:11:07 2013 +0000
+++ b/player.hpp Tue Jun 18 14:10:34 2013 +0000
@@ -47,7 +47,7 @@
float timeInSong;
Ticker sampleTicker;
Song *song;
- Song::actions_t::iterator nextAction;
+ Action *nextAction;
unsigned actionsDone;
SongPlayer() : playing(0)
@@ -68,26 +68,25 @@
}
bool startSong(Song *_song) {
- if (song) delete song;
song = _song;
- nextAction = song->getActions().begin();
+ nextAction = song->getActions();
timeInSong = 0.0;
actionsDone = 0;
fprintf(stderr, "starting %s: ", song->getSampleFileName());
if (fp) fclose(fp);
fp = fopen(song->getSampleFileName(), "rb");
+ if (!fp) goto on_error;
fprintf(stderr, "opened, ");
- if (!fp) return false;
+ if (fseek(fp, 0, SEEK_END)) goto on_error;
fprintf(stderr, "seekend, ");
- if (fseek(fp, 0, SEEK_END)) return false;
long fileSize = ftell(fp);
fprintf(stderr, "size=%d, ", fileSize);
- if (fileSize < 0) return false;
+ if (fileSize < 0) goto on_error;
- if (fseek(fp, 0, SEEK_SET)) return false;
+ if (fseek(fp, 0, SEEK_SET)) goto on_error;
fprintf(stderr, "rewound, ");
chunksRemaining = nChunks = fileSize / BUFFER_SIZE;
@@ -96,11 +95,16 @@
fprintf(stderr, "chunks=%d expected=%f seconds\r\n", nChunks, nChunks * SECONDS_PER_CHUNK);
if (!loadNextChunk()) {
fprintf(stderr, "first chunk empty!\r\n");
- return false;
+ goto on_error;
}
sampleTicker.attach_us(this, &SongPlayer::playNextSample, SAMPLE_PERIOD_USEC);
return true;
+
+on_error:
+ if (fp) fclose(fp);
+ fp = 0;
+ return false;
}
// swap loading/playing buffers;
@@ -133,7 +137,7 @@
// look at loading buffer; load only if necessary.
bool loadIfNecessary() {
if (loading->isDone()) {
- fprintf(stderr, "*");
+ fprintf(stderr, "*");
timeInSong += SECONDS_PER_CHUNK;
return loadNextChunk();
} else {
@@ -143,10 +147,10 @@
void playEntireSong(Song *_song) {
if (!startSong(_song)) return;
-
+ Action* lastAction = song->getActions() + song->getNumActions();
while (!isDone()) {
- while (nextAction != song->getActions().end() && nextAction->actIfPast(timeInSong)) {
- fprintf(stderr, ".");
+ while (nextAction < lastAction && nextAction->actIfPast(timeInSong)) {
+ fprintf(stderr, ".");
actionsDone++;
nextAction++;
}
--- a/song.cpp Tue Jun 18 13:11:07 2013 +0000
+++ b/song.cpp Tue Jun 18 14:10:34 2013 +0000
@@ -15,16 +15,15 @@
char const *Song::sampleExtension = "raw";
// class static
unsigned const Song::NO_FISH = MAX_FISH + 1;
+// one song, re-used
+Song Song::theSong;
// _name is relative to BASS_DIRECTORY
// class static
Song *Song::newSong(char const *_name)
{
- Song *s = new Song;
- if (!s) {
- fprintf(stderr, "new Song == 0\r\n");
- return 0;
- }
+ Song *s = &theSong;
+ s->reset();
if (! s->parseFilename(_name)) {
fprintf(stderr, "parseFilename(%s) failed\r\n", _name);
goto on_error;
@@ -38,7 +37,6 @@
return s;
on_error:
- delete s;
return 0;
}
@@ -131,11 +129,11 @@
}
// fprintf(stderr, "%d add %f %f %s\r\n", line, startTime, endTime, outName);
- actions.push_back(Action(startTime, bass->onState(), out, outName));
- actions.push_back(Action(endTime, bass->offState(), out, outName));
+ addAction(startTime, bass->onState(), out);
+ addAction(endTime, bass->offState(), out);
}
- fprintf(stderr, "Added %d actions\r\n", actions.size());
- std::sort(actions.begin(), actions.end()); // sort actions by time
+ fprintf(stderr, "Added %d actions\r\n", numActions);
+ qsort(actions, numActions, sizeof(Action), &Action::compare);
retval = true;
done:
@@ -143,3 +141,4 @@
fclose(txtfile);
return retval;
}
+
--- a/song.hpp Tue Jun 18 13:11:07 2013 +0000
+++ b/song.hpp Tue Jun 18 14:10:34 2013 +0000
@@ -10,22 +10,24 @@
class Song
{
public:
- typedef std::vector<Action> actions_t;
+ typedef Action actions_t[ MAX_ACTIONS_PER_SONG ];
// _name is relative to BASS_DIRECTORY
// return a pointer to a fully read-in Song if valid
- // also adds new song to songs
static Song *newSong(char const *_name);
- Song() : sequenceNumber(0), whichFish(NO_FISH), basename(0), extension(0) {
- fullname[0] = 0;
- actions.reserve(MAX_ACTIONS_PER_SONG);
+
+ void reset() {
+ sequenceNumber = 0;
+ whichFish = NO_FISH;
+ basename = 0;
+ extension = 0;
+ numActions = 0;
}
- ~Song() {
- actions.clear();
+
+ BillyBass * myFish() {
+ return BillyBass::bassNumber(whichFish);
}
-
- BillyBass * myFish() { return BillyBass::bassNumber(whichFish); }
bool isValid() const {
return basename != 0 && whichFish != NO_FISH;
}
@@ -48,24 +50,37 @@
strcpy(extension, textExtension);
return fullname;
}
- actions_t &getActions() {
+ Action *getActions() {
return actions;
}
+ bool addAction(float _time, int _state, DigitalOut* _out) {
+ if (numActions >= MAX_ACTIONS_PER_SONG) return false;
+ actions[numActions++].set(_time, _state, _out);
+ return true;
+ }
+ unsigned getNumActions() const {
+ return numActions;
+ }
void print(FILE *f) {
fprintf(f, "%s fish=%u seq=%u\r\n", getSampleFileName(), whichFish, sequenceNumber);
- for (actions_t::const_iterator action_it = actions.begin(); action_it != actions.end(); action_it++) {
- Action const &action = *action_it;
- fprintf(f, "%0.02f %s %d\r\n", action.actionTime, action.outputName, action.desiredState ? 1 : 0);
+ Action *lastAction = actions + numActions;
+ for (Action *action = actions; action < lastAction; action++) {
+ fprintf(f, "%0.02f %s %d\r\n", action->actionTime, myFish()->outputName(action->output), action->desiredState);
}
}
protected:
+ Song() {
+ reset();
+ }
+ ~Song() {}
static char const directoryName[ BASS_DIRECTORY_LENGTH + 1 ];
static unsigned const NO_FISH;
static char const *textExtension;
static char const *sampleExtension;
+ static Song theSong;
unsigned sequenceNumber; // 0-relative
unsigned whichFish; // 0-relative
@@ -73,6 +88,7 @@
char *basename; // points into fullname
char *extension; // points into fullname
actions_t actions;
+ unsigned numActions;
};
#endif // __included_song_hpp
Ned Konz