[FFmpeg-soc] [soc] libavsequencer [PATCH 04/08] Track / pattern handling public API header file.
Vitor Sessak
vitor1001 at gmail.com
Tue Jul 13 22:02:29 CEST 2010
On 07/13/2010 09:35 PM, Sebastian Vater wrote:
> Vitor Sessak a écrit :
>> On 07/11/2010 10:07 PM, Sebastian Vater wrote:
>>> typedef struct AVSequencerTrackData {
>>> /** Array of pointers containing all effects used by this
>>> track. */
>>> AVSequencerTrack **effects_data;
>>>
>>> /** Which octave the note is played upon, if note is a
>>> positive value (defaults to 4). */
>>> uint8_t octave;
>>> #define AVSEQ_TRACK_DATA_OCTAVE 4
>>> #define AVSEQ_TRACK_DATA_OCTAVE_MIN 0
>>> #define AVSEQ_TRACK_DATA_OCTAVE_MAX 9
>>
>> Those MAX/MIN are characteristics of the player, no? So...
>
> More a display octaves below 0 and beyond 9 problem, most trackers
> allocate a single character for displaying the octave (display in
> decimal), therefore octaves< 0 ||> 9 are a serious problem. Also it's
> mostly useless, consider base octave 4 or 5. Playing an instrument such
> far away either causes silence (most instruments even fail to give
> hearable audible sound even at octave 2 and 8).
>
> Also track data is not a player structure, it's a track editor structure
> USED by the player as well. The data here is supposed to be directly
> editable by the user.
In this case it is not a hard limit. It is better than to put a comment
instead of the defines:
/** Which octave the note is played upon, if note is a
positive value (defaults to 4). Sane values are in
the [0:9] range, expect trouble with most trackers
if you use other values. */
>>> /** Number of instrument to be played or 0 to take previous one. */
>>> uint16_t instrument;
>>
>> Why 0 to take previous one? This forces your array to start at 1 and
>> IMHO does not simplify any code. In the player you can always do
>
> Changing this will seriously break compatibility to ANY tracker,
The loader can do
if (read_instrument == 0) instrument = last_instrument;
and no compatibility is lost.
> ALL
> trackers I know use instrument as an identifier to use the previously
> intialized instrument.
That's a good point. If (instrument == 0) obviously means "last
instrument" for everyone who has a good experience of tracker formats,
this improves readability instead of obfuscating it.
> This field also is supposed to be directly
> editable by the user, and the user doesn't want to repeat the instrument
> number all and all again.
The user is a software, it can hide it from the user.
>> if (instrument == previous_instrument) {...}
>
> Please note that instrument number 0 also differs whether you play the
> track in once mode (pattern play mode) and the instrument number was
> initialized in the previous order. All trackers don't output sound in
> that case, changing this would make this part incompatible.
That's another good point, so I'm fine with instrument==0 meaning last
instrument. But if the behavior of setting instrument==0 is different of
the behavior of setting instrument==last_instrument, it should be
documented somewhere.
>>> /** AVSequencerTrackData pointer to array of track data. */
>>> AVSequencerTrackData *data;
>>
>> This naming bothers me a little. If AVSequencerTrackData contains the
>> track data, what does AVSequencerTrack contains?
>
> TrackData is the octave, note, effect and effect data for each row,
> Track itself defines the structure containing it, i.e. number of rows,
> maybe track name, etc.
Maybe AVSequencerRowData then?
>>
>>>
>>> /**
>>> * Song track effect structure, This structure is actually for one row
>>> * and therefore actually pointed as an array with the amount of
>>> * rows of the whole track.
>>> * New fields can be added to the end with minor version bumps.
>>> * Removal, reordering and changes to existing fields require a major
>>> * version bump.
>>> */
>>> typedef struct AVSequencerTrackEffect {
>>
>>> /** Unused and reserved for future expansions, leave 0 for now. */
>>> uint8_t reserved;
>>
>> Can be removed.
>
> Fixed.
>
>>
>>> /** Effect command byte. */
>>> uint8_t command;
>>
>>> /** Command types. */
>>
>> Doxygen will not parse it as you want. Better just
>>
>> /* Command types. */
>>
>>> /** Note effects (00-1F). */
>>> #define AVSEQ_TRACK_EFFECT_NOTE_MIN 0x00
>>> #define AVSEQ_TRACK_EFFECT_NOTE_MAX 0x1F
>>>
>>> /** Volume control related effects (20-2F). */
>>> #define AVSEQ_TRACK_EFFECT_VOLUME_MIN 0x20
>>> #define AVSEQ_TRACK_EFFECT_VOLUME_MAX 0x2F
>>>
>>> /** Panning control related effects (30-3F). */
>>> #define AVSEQ_TRACK_EFFECT_PANNING_MIN 0x30
>>> #define AVSEQ_TRACK_EFFECT_PANNING_MAX 0x3F
>>>
>>> /** Track and channel control related effects (40-4F). */
>>> #define AVSEQ_TRACK_EFFECT_TRACK_MIN 0x40
>>> #define AVSEQ_TRACK_EFFECT_TRACK_MAX 0x4F
>>>
>>> /** Instrument, sample and synth control related effects
>>> (50-5F). */
>>> #define AVSEQ_TRACK_EFFECT_INSTRUMENT_MIN 0x50
>>> #define AVSEQ_TRACK_EFFECT_INSTRUMENT_MAX 0x5F
>>>
>>> /** Global control related effects (60-7E). */
>>> #define AVSEQ_TRACK_EFFECT_GLOBAL_MIN 0x60
>>> #define AVSEQ_TRACK_EFFECT_GLOBAL_MAX 0x7E
>>
>> This is ugly and fragile (what would you do if a new format shows up
>> with a new volume effect). Why not an array instead?
>
> This would require extending using 0x80-0xFF command effect which would
> conflict with synth sound handling (see there at the synth sound
> instructions).
Ok, let me pose the question differently. Suppose we have an effect foo.
In MOD, effect foo is command 0x66 while in XM it is command 0x55. What
is the value of AVSEQ_TRACK_EFFECT_CMD_FOO? Or such thing never happens?
>> static const Enum EffectType effect_type[AVSEQ_EFFECTS_NUMBER] = {
>> [AVSEQ_TRACK_EFFECT_CMD_ARPEGGIO] = AVSEQ_TRACK_EFFECT_NOTE,
>> [AVSEQ_TRACK_EFFECT_CMD_PORTA_UP] = AVSEQ_TRACK_EFFECT_NOTE,
>> [...]
>> };
>>
>> Note how easy would be change it to a struct to add more information
>> about each effect.
>
> ??? I really don't understand this approach besides using enums.
The idea was replacing
if (cmd >= 0x20 && cmd <= 0x2F) // check if it is a volume command
by
if (effect_type[cmd] == AVSEQ_TRACK_EFFECT_VOLUME)
-Vitor
More information about the FFmpeg-soc
mailing list