[FFmpeg-soc] [soc] libavsequencer [PATCH 04/08] Track / pattern handling public API header file.
Vitor Sessak
vitor1001 at gmail.com
Tue Jul 13 12:43:02 CEST 2010
On 07/11/2010 10:07 PM, Sebastian Vater wrote:
> Michael Niedermayer a écrit :
>> i guess alot of these #defines could be enums and then the correct types
>> could be used instead of int*_t
>>
>> [...]
>>
>
> Hi Michael! I will change them the next days, this will incorporate a
> lot of changes to player.c also. Anyway, I have updated track.h, so new
> patch attached anyway.
> /*
> * AVSequencer track and pattern management
> * Copyright (c) 2010 Sebastian Vater <cdgs.basty at googlemail.com>
> *
> * This file is part of FFmpeg.
> *
> * FFmpeg is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> * License as published by the Free Software Foundation; either
> * version 2.1 of the License, or (at your option) any later version.
> *
> * FFmpeg is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> * Lesser General Public License for more details.
> *
> * You should have received a copy of the GNU Lesser General Public
> * License along with FFmpeg; if not, write to the Free Software
> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> */
>
> #ifndef AVSEQUENCER_TRACK_H
> #define AVSEQUENCER_TRACK_H
>
> #include "libavformat/avformat.h"
> #include "libavsequencer/avsequencer.h"
>
> /**
> * Song track data 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 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...
> /** Note to be played (see defines below, n is octave number). */
> int8_t note;
> /** C-n */
> #define AVSEQ_TRACK_DATA_NOTE 1
> #define AVSEQ_TRACK_DATA_NOTE_C 1
> #define AVSEQ_TRACK_DATA_NOTE_MIN AVSEQ_TRACK_DATA_NOTE_MIN
>
> /** C#n = Dbn */
> #define AVSEQ_TRACK_DATA_NOTE_C_SHARP 2
>
> /** D-n */
> #define AVSEQ_TRACK_DATA_NOTE_D 3
>
> /** D#n = Ebn */
> #define AVSEQ_TRACK_DATA_NOTE_D_SHARP 4
>
> /** E-n */
> #define AVSEQ_TRACK_DATA_NOTE_E 5
>
> /** F-n */
> #define AVSEQ_TRACK_DATA_NOTE_F 6
>
> /** F#n = Gbn */
> #define AVSEQ_TRACK_DATA_NOTE_F_SHARP 7
>
> /** G-n */
> #define AVSEQ_TRACK_DATA_NOTE_G 8
>
> /** G#n = Abn */
> #define AVSEQ_TRACK_DATA_NOTE_G_SHARP 9
>
> /** A-n */
> #define AVSEQ_TRACK_DATA_NOTE_A 10
>
> /** A#n = Bbn */
> #define AVSEQ_TRACK_DATA_NOTE_A_SHARP 11
>
> /** B-n = H-n */
> #define AVSEQ_TRACK_DATA_NOTE_B 12
> #define AVSEQ_TRACK_DATA_NOTE_H FF_AVSEQ_TRACK_DATA_NOTE_B
> #define AVSEQ_TRACK_DATA_NOTE_MAX FF_AVSEQ_TRACK_DATA_NOTE_B
>
> /** --- = first special empty note */
> #define AVSEQ_TRACK_DATA_NOTE_SPECIAL 0
> #define AVSEQ_TRACK_DATA_NOTE_NONE FF_AVSEQ_TRACK_DATA_NOTE_SPECIAL
>
> /** ^^^ = note kill */
> #define AVSEQ_TRACK_DATA_NOTE_KILL -1
>
> /** ^^- = note off */
> #define AVSEQ_TRACK_DATA_NOTE_OFF -2
>
> /** === = keyoff note */
> #define AVSEQ_TRACK_DATA_NOTE_KEYOFF -3
>
> /** -|- = hold delay */
> #define AVSEQ_TRACK_DATA_NOTE_HOLD_DELAY -4
>
> /** -\- = note fade */
> #define AVSEQ_TRACK_DATA_NOTE_FADE -5
>
> /** END = pattern end marker */
> #define AVSEQ_TRACK_DATA_NOTE_END -16
> /** 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
if (instrument == previous_instrument) {...}
> /** C-4 = default tone */
> #define AVSEQ_TRACK_DATA_TONE ((FF_AVSEQ_TRACK_DATA_OCTAVE << 8) | FF_AVSEQ_TRACK_DATA_NOTE)
>
> /** Number of effects used by this track. */
> uint16_t effects;
> } AVSequencerTrackData;
>
> /**
> * Song track structure.
> * 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 AVSequencerTrack {
> /** Metadata information: Original track file name, track
> title, track message, track artist, track album,
> track begin and finish date of composition and comment. */
> AVMetadata *metadata;
> /** 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?
> /** Last valid row of track (defaults to 63 = 0x3F) which
> is the default for most trackers (64 rows per pattern). */
> uint16_t last_row;
> #define AVSEQ_TRACK_LAST_ROW 63
> #define AVSEQ_TRACK_LENGTH ((FF_AVSEQ_TRACK_LAST_ROW) + 1)
> #define AVSEQ_TRACK_LENGTH_MIN 0
> #define AVSEQ_TRACK_LENGTH_MAX 65536
>
> /** Track global volume (defaults to 255 = no volume scaling). */
> uint8_t volume;
> #define AVSEQ_TRACK_VOLUME 255
>
> /** Sub-volume level for this track. This is basically track
> global volume divided by 256, but the sub-volume doesn't
> account into actual mixer output (defaults 0). */
> uint8_t sub_volume;
> #define AVSEQ_TRACK_SUB_VOLUME 0
>
> /** Stereo panning level for this track (defaults to
> -128 = central stereo panning). */
> int8_t panning;
> #define AVSEQ_TRACK_PANNING -128
>
> /** Stereo track sub-panning level for this channel. This is
> basically track panning divided by 256, but the sub-panning
> doesn't account into actual mixer output (defaults 0). */
> uint8_t sub_panning;
> #define AVSEQ_TRACK_SUB_PANNING 0
>
> /** Track transpose. Add this value to octave * 12 + note to
> get the final octave / note played (defaults to 0). */
> int8_t transpose;
> #define AVSEQ_TRACK_TRANSPOSE 0
>
> /** Compatibility flags for playback. There are rare cases
> where track handling can not be mapped into internal
> playback engine and have to be handled specially. For
> each sub-song which needs this, this will define new
> flags which tag the player to handle it to that special
> way. */
> uint8_t compat_flags;
> #define AVSEQ_TRACK_COMPAT_FLAG_SAMPLE_OFFSET 0x01 ///< Sample offset beyond end of sample will be ignored (IT compatibility)
> #define AVSEQ_TRACK_COMPAT_FLAG_TONE_PORTA 0x02 ///< Share tone portamento memory with portamentoes and unlock tone portamento samples and adjusts frequency to: new_freq = freq * new_rate / old_rate. If an instrument number is given the envelope will be retriggered (IT compatibility).
> #define AVSEQ_TRACK_COMPAT_FLAG_SLIDES 0x04 ///< Portamentos of same type share the same memory (e.g. porta up/fine porta up)
> #define AVSEQ_TRACK_COMPAT_FLAG_VOLUME_SLIDES 0x08 ///< All except portamento slides share the same memory (e.g. volume/panning slides)
> #define AVSEQ_TRACK_COMPAT_FLAG_OP_SLIDES 0x10 ///< Oppositional portamento directions don't share the same memory (e.g. porta up and porta down)
> #define AVSEQ_TRACK_COMPAT_FLAG_OP_VOLUME_SLIDES 0x20 ///< Oppositional non-portamento slide directions don't share the same memory
> #define AVSEQ_TRACK_COMPAT_FLAG_VOLUME_PITCH 0x40 ///< Volume & pitch slides share same memory (S3M compatibility)
>
> /** Track playback flags. Some sequencers feature
> surround panning or allow initial reverse playback,
> different timing methods which have all to be taken
> care specially in the internal playback engine. */
> uint8_t flags;
> #define AVSEQ_TRACK_FLAG_USE_TIMING 0x01 ///< Use track timing fields
> #define AVSEQ_TRACK_FLAG_SPD_TIMING 0x02 ///< SPD speed timing instead of BpM
> #define AVSEQ_TRACK_FLAG_PANNING 0x04 ///< Use track panning and sub-panning fields
> #define AVSEQ_TRACK_FLAG_SURROUND 0x08 ///< Use track surround panning
> #define AVSEQ_TRACK_FLAG_REVERSE 0x10 ///< Playback of track in backward direction
>
> /** Initial number of frames per row, i.e. sequencer tempo
> (defaults to 6 as in most tracker formats). */
> uint16_t frames;
> #define AVSEQ_TRACK_FRAMES 6
>
> /** Initial speed multiplier, i.e. nominator which defaults
> to disabled = 0. */
> uint8_t speed_mul;
> #define AVSEQ_TRACK_SPEED_MUL 0
>
> /** Initial speed divider, i.e. denominator which defaults
> to disabled = 0. */
> uint8_t speed_div;
> #define AVSEQ_TRACK_SPEED_DIV 0
>
> /** Initial MED style SPD speed (defaults to 33 as in
> OctaMED Soundstudio). */
> uint16_t spd_speed;
> #define AVSEQ_TRACK_SPD_SPEED 33
>
> /** Initial number of rows per beat (defaults to 4 rows are a beat). */
> uint16_t bpm_tempo;
> #define AVSEQ_TRACK_BPM_TEMPO 4
>
> /** Initial beats per minute speed (defaults to 50 Hz => 125 BpM). */
> uint16_t bpm_speed;
> #define AVSEQ_SONG_BPM_SPEED 125
>
> /** Array of pointers containing every unknown data field where
> the last element is indicated by a NULL pointer reference. The
> first 64-bit of the unknown data contains an unique identifier
> for this chunk and the second 64-bit data is actual unsigned
> length of the following raw data. Some formats are chunk based
> and can store information, which can't be handled by some
> other, in case of a transition the unknown data is kept as is.
> Some programs write editor settings for tracks in those chunks,
> which then won't get lost in that case. */
> uint8_t **unknown_data;
> } AVSequencerTrack;
>
> /**
> * 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.
> /** 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?
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.
BTW, using Arpeggio == 0x00 is specific for some format or some ad-hoc
choice? If it is ad-hoc, it should not be part of the Doxy comment, it
is not useful information.
> /** User customized effect for trigger in demos, etc. */
> #define AVSEQ_TRACK_EFFECT_USER 0x7F
>
> /** Note effect commands.
> 0x00 - Arpeggio:
> Data word consists of two 8-bit pairs named xx and yy
> where xx is the first halftone and yy the second halftone.
> Both xx and yy are signed values which means that a
> negative value is a backward arpeggio. */
> #define AVSEQ_TRACK_EFFECT_CMD_ARPEGGIO 0x00
[...]
-Vitor
More information about the FFmpeg-soc
mailing list