From: <wha...@us...> - 2011-07-02 16:26:17
|
Revision: 7485 http://planeshift.svn.sourceforge.net/planeshift/?rev=7485&view=rev Author: whacko88 Date: 2011-07-02 16:26:11 +0000 (Sat, 02 Jul 2011) Log Message: ----------- handled musical sheet's tonality and better handling of polyphony Modified Paths: -------------- soc/2011/sound/src/plugins/common/soundmanager/instrument.h soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp soc/2011/sound/src/plugins/common/soundmanager/songstream.h Modified: soc/2011/sound/src/plugins/common/soundmanager/instrument.h =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/instrument.h 2011-07-01 23:00:38 UTC (rev 7484) +++ soc/2011/sound/src/plugins/common/soundmanager/instrument.h 2011-07-02 16:26:11 UTC (rev 7485) @@ -115,7 +115,7 @@ * * @param fileName the file that contain the note's sound. * @param note a char representing the note in the British English notation - * (i.e. A, B, C, ..., G). + * (i.e. A, B, C, ..., G). * @param alter 1 if the note is altered by a sharp, -1 for a flat and 0 if * it is not altered. * @param octave 4 for the central octave in piano. Modified: soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp 2011-07-01 23:00:38 UTC (rev 7484) +++ soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp 2011-07-02 16:26:11 UTC (rev 7485) @@ -45,7 +45,7 @@ noteBuffer = 0; if(data->instrument->GetPolyphony() > 1) { - copyNoteBuffer = new char[songData->instrument->GetLongestNoteSize()]; + copyNoteBuffer = new char[data->instrument->GetLongestNoteSize()]; } else { @@ -95,7 +95,7 @@ void SndSysSongStream::AdvancePosition(size_t frameDelta) { size_t neededBytes; - size_t neededBuffer; + int neededBuffer; const csSndSysSoundFormat* dataFormat = soundData->GetFormat(); // if the stream is in pause or we have already finished to read don't advance @@ -226,6 +226,8 @@ // TODO support for <tie> and chords with different duration of their notes bool SndSysSongStream::GetNextChord() { + uint nChordNotes; // current number of notes in the chord + bool chordFound = false; bool notesLeft = false; char step; @@ -279,6 +281,28 @@ if(notes->GetNextPosition() == currentNote) { note = notes->Next(); + + // skipping chords that this instrument can't play + if(note->GetNode("chord").IsValid()) + { + if(notes->HasNext()) + { + currentNote++; + continue; + } + else if(currentMeasure + 1 == songData->measures.GetSize()) + { + noteBufferSize = 0; + return true; + } + else + { + currentMeasure++; + currentNote = 0; + return GetNextChord(); + } + } + break; } notes->Next(); @@ -299,6 +323,9 @@ octave = pitch->GetNode("octave")->GetContentsValueAsInt(); divisions = note->GetNode("duration")->GetContentsValueAsInt(); + // adjusting alteration depending on the tonality + AdjustAlteration(step, alter); + // computing note duration in seconds duration = timePerDivision * divisions; @@ -307,50 +334,56 @@ lastNoteSize += noteBufferSize; // handling chords - if(songData->instrument->GetPolyphony() > 1) + nChordNotes = 1; + while(notes->HasNext() && nChordNotes < songData->instrument->GetPolyphony()) { - bool chordFound = false; - - while(notes->HasNext()) + note = notes->Next(); + if(note->GetNode("chord") == 0) { - note = notes->Next(); - if(note->GetNode("chord") == 0) - { - notesLeft = true; - break; - } + notesLeft = true; + break; + } - // copying buffer if needed - // remember that noteBuffer can't be modified, otherwise the instrument's data will be damaged - if(!chordFound) - { - memcpy(copyNoteBuffer, noteBuffer, noteBufferSize); - chordFound = true; - } + // updating current state + nChordNotes++; + currentNote++; - // getting data of the new note - pitch = note->GetNode("pitch"); - step = *(pitch->GetNode("step")->GetContentsValue()); - alterNode = pitch->GetNode("alter"); - if(alterNode == 0) - { - alter = 0; - } - else - { - alter = alterNode->GetContentsValueAsInt(); - } - octave = pitch->GetNode("octave")->GetContentsValueAsInt(); - songData->instrument->AddNoteToChord(step, alter, octave, copyNoteBuffer, noteBufferSize); + // copying buffer if needed + // remember that noteBuffer can't be modified, otherwise the instrument's data will be damaged + if(!chordFound) + { + memcpy(copyNoteBuffer, noteBuffer, noteBufferSize); + chordFound = true; } - // fixing noteBuffer if a chord has been found - if(chordFound) + // getting data of the new note + pitch = note->GetNode("pitch"); + step = *(pitch->GetNode("step")->GetContentsValue()); + alterNode = pitch->GetNode("alter"); + if(alterNode == 0) { - noteBuffer = copyNoteBuffer; + alter = 0; } + else + { + alter = alterNode->GetContentsValueAsInt(); + } + octave = pitch->GetNode("octave")->GetContentsValueAsInt(); + + // adjusting alteration depending on the tonality + AdjustAlteration(step, alter); + + // add waves + songData->instrument->AddNoteToChord(step, alter, octave, copyNoteBuffer, noteBufferSize); } + // fixing noteBuffer if a chord has been found + if(chordFound) + { + noteBuffer = copyNoteBuffer; + } + + // is this the end of the measure? // HasNext() is necessary if we didn't find chords if(notesLeft || notes->HasNext()) @@ -398,6 +431,101 @@ } } +void SndSysSongStream::AdjustAlteration(char pitch, int &alter) +{ + if(alter != 0) + { + return; + } + + if(songData->fifths > 0) + { + // NOTE: here there are no breaks on purpose and + // the order of the case count!! Do not change it! + switch(songData->fifths) + { + case 7: + if(pitch == 'B') + { + alter++; + } + case 6: + if(pitch == 'E') + { + alter++; + } + case 5: + if(pitch == 'A') + { + alter++; + } + case 4: + if(pitch == 'R') + { + alter++; + } + case 3: + if(pitch == 'G') + { + alter++; + } + case 2: + if(pitch == 'C') + { + alter++; + } + case 1: + if(pitch == 'F') + { + alter++; + } + } + } + else if(songData->fifths < 0) + { + // NOTE: here there are no breaks on purpose and + // the order of the case count!! Do not change it! + switch(songData->fifths) + { + case -7: + if(pitch == 'F') + { + alter--; + } + case -6: + if(pitch == 'C') + { + alter--; + } + case -5: + if(pitch == 'G') + { + alter--; + } + case -4: + if(pitch == 'D') + { + alter--; + } + case -3: + if(pitch == 'A') + { + alter--; + } + case -2: + if(pitch == 'E') + { + alter--; + } + case -1: + if(pitch == 'B') + { + alter--; + } + } + } +} + // TODO support loop notes (like organ, the sound can be persisent and does not end into silence) // TODO support for dynamics void SndSysSongStream::CopyNoteIntoBuffer() Modified: soc/2011/sound/src/plugins/common/soundmanager/songstream.h =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/songstream.h 2011-07-01 23:00:38 UTC (rev 7484) +++ soc/2011/sound/src/plugins/common/soundmanager/songstream.h 2011-07-02 16:26:11 UTC (rev 7485) @@ -112,6 +112,17 @@ bool GetNextChord(); /** + * This is an helper function that adjust the alteration of the note depending + * on the tonality of the song. If the note is already altered (alter != 0) + * nothing happens. + * + * @param pitch a char representing the note in the British English notation + * (i.e. A, B, C, ..., G). + * @param alter the alteration variable that must be adjusted. + */ + void AdjustAlteration(char pitch, int &alter); + + /** * Copies the note in noteBuffer into m_pPreparedDataBuffer and add 0 at its * end if lastNoteDuration > noteBufferSize. This method assumes that the * prepared data buffer is already large enough. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |