line source
+ − Generating ringtone melodies through the Calypso DSP
+ − ====================================================
+ −
+ − The DSP in the Calypso and other GSM DBB chips from TI includes a built-in
+ − capability for generating ringtone melodies to be played through a loudspeaker
+ − driven by the ABB, without using an external melody generator chip. More
+ − specifically, the DSP in question supports two flavors of internal melody
+ − generation, called Melody E1 and Melody E2 - although it is unclear whether
+ − Melody E2 is implemented in the DSP ROM or in the DSP code patches downloaded
+ − by TI's firmwares.
+ −
+ − The Melody E1 mechanism produces simple polyphonic melodies with up to 8
+ − simultaneous notes; these melodies consist of simple sine waves generated by
+ − the DSP as commanded by the bits read from the melody file as explained below.
+ − Melody E2 is a more complex mechanism for producing melodies (also polyphonic
+ − with up to 8 simultaneous notes) using the sounds of specific instruments,
+ − rather than simple sine waves, but we currently lack the bits required in order
+ − to understand or exercise it, hence our current focus is on the simpler Melody
+ − E1 mechanism.
+ −
+ − How these melodies are played
+ − =============================
+ −
+ − TI's RiViera Audio Service firmware component provides a front-end to the
+ − various audio services provided by the lower-level DSP+L1 combo. In the case
+ − of Melody E1 and Melody E2 features, the combination of the DSP and TI's
+ − ARM-side L1 code effectively defines the format of the melody bits themselves,
+ − but the RiViera Audio Service takes care of reading these bits from FFS and
+ − feeding them to L1.
+ −
+ − To play an E1 format melody, the UI code needs to call audio_melody_E1_start();
+ − one of the arguments to this API function is the FFS absolute pathname of the
+ − melody file. The API function will open this file and pass the open file
+ − descriptor along with other parameters in the message posted to the Audio task;
+ − the latter task will prefetch the first buffer-full of melody bits from the file
+ − and then post an MMI_MELODY0_START_REQ message to the L1A task. The Melody E1
+ − handler in L1A will set up some preliminaries and fire up the Melody E1 L1S
+ − task, and the latter will then pass the melody bits to the DSP at appropriate
+ − times.
+ −
+ − Melody E1 file format
+ − =====================
+ −
+ − We have found a rather terse and not particularly thorough description of the
+ − Melody E1 bit format on pages 160 through 163 of this PDF document:
+ −
+ − https://www.freecalypso.org/LoCosto-docs/PSL1DOC/L1/L1M_AS001_1.pdf
+ −
+ − This description is not complete enough to enable proper understanding or
+ − implementation, but by combining it with a study of the L1A and L1S code that
+ − reads these bits and passes most of them to the DSP, we have reconstructed a
+ − somewhat more complete picture.
+ −
+ − The format is word-oriented, i.e., the basic unit of data in a Melody E1 file
+ − is the 16-bit word. Most of these words are passed to the DSP for final
+ − interpretation inside the latter, hence we won't be able to have a 100% certain
+ − understanding of what happens there unless we can find the source for the DSP
+ − ROM code or expend a Herculean effort to reverse-engineer it, but some of the
+ − words are interpreted and acted upon by the ARM-side L1 firmware code, which we
+ − have source-reconstructed already. When these words are written in a disk or
+ − FFS file, the byte order is little-endian, as it is ARM code that reads these
+ − 16-bit words from a byte-oriented source.
+ −
+ − The very first word in a Melody E1 file gives the global list of oscillators
+ − used by this melody; this word is read by the L1A code before the L1S task is
+ − fired up. The presence of this word is not documented at all in the terse
+ − description given in L1M_AS001_1.pdf, and our attempts at producing our own E1
+ − melodies were going nowhere until we discovered that this word is needed through
+ − the study of our reconstructed TCS211 L1 code. This initial word corresponds
+ − to the osc-set line in our ASCII format.
+ −
+ − After the initial word giving the global oscillator set, the melody file
+ − consists of what we shall call time blocks. Each time block begins with a time
+ − descriptor word which is interpreted and acted upon by ARM L1S code, followed
+ − by 0 to 8 oscillator descriptors which are loaded into DSP API words. These
+ − words are described in TI's document, so we are just going to supplement that
+ − description wherever we have discovered something to the contrary.
+ −
+ − The lower byte of the time descriptor word tells the L1S task how long it should
+ − wait before loading the following oscillator descriptors into the DSP. It
+ − appears that TI's intent was for this time value to be measured in 20 ms audio
+ − frames, but what the ARM L1S code actually does is multiply the given time value
+ − by 4 and use the result as the number of TDMA frames to count - the L1S code
+ − executes on every TDMA frame. 13 TDMA frames equal 60 ms, thus 4 TDMA frames
+ − do not exactly equal 20 ms, but come a little short. It is not clear whether
+ − the melody files generated by TI and/or their customers account for this
+ − discrepancy or not. In any case, the time value given in the file needs to be
+ − non-zero - putting a zero in there will cause the L1S counter to be set to 65535
+ − TDMA frames (a 16-bit unsigned counter loaded with 0 and decremented by one),
+ − which is probably not what you want.
+ −
+ − The upper byte of the time descriptor word is a bit mask indicating which DSP
+ − oscillators are to be loaded at this time. This bit mask byte can be zero, in
+ − which case the time block consists of just the time descriptor word. However,
+ − the L1S code does absolutely nothing to the DSP in this case, hence an empty
+ − (no oscillators) time block is indistinguishable from adding the time to the
+ − following non-empty block. But the largest time value that can fit in the byte
+ − is 255, hence empty time blocks can be used to produce larger time deltas.
+ − A time descriptor with zeros in both upper and lower bytes indicates the end of
+ − the melody; this terminator is required.
+ −
+ − Now we come to the interesting part: the oscillator descriptors that are loaded
+ − into the DSP to cause the actual melody generation to occur. The DSP's NDB API
+ − page contains 4 words for each of the 8 oscillators, and these NDB API words are
+ − where the oscillator descriptor words from the melody file ultimately go.
+ −
+ − Please refer to the description of the ml_load1 and ml_load2 bits on page 162
+ − of TI's L1M_AS001_1.pdf document. Now here is what the L1S code actually does:
+ − first it loads 2 words from the file buffer into the DSP's NDB page - yes,
+ − directly into there. Then it does the following logic (code simplified from
+ − the actual into more readable pseudocode):
+ −
+ − load_size = 0;
+ − if (word1 & ml_load1)
+ − load_size++;
+ − if (word1 & ml_load2)
+ − load_size++;
+ − if (load_size)
+ − load load_size words at word2 address in the DSP's NDB page
+ −
+ − This logic is peculiar: what happens if ml_load2 is set but not ml_load1? The
+ − result will be that the word meant to be word3 (the envelope word) will get
+ − loaded into the word2 location in the DSP's NDB page. Unless the DSP actually
+ − checks the ml_load bits and expects the envelope word in the word2 location in
+ − this case, which I highly doubt, this L1S behaviour looks like a bug to me - so
+ − don't use the word3 present but not word2 combination in your melodies.
+ −
+ − It appears that these ml_load1 and ml_load2 bits are only checked by the L1S
+ − code and ignored by the DSP. I say so because when I tried creating a melody
+ − in which word2 and word3 were always omitted, the result was bogus. It appears
+ − that the first time a given oscillator is loaded, all 4 words must always be
+ − given, otherwise the DSP will act on whatever garbage happens to be in those
+ − NDB API words from before. When the same oscillator is subsequently reloaded,
+ − omitting word2 and/or word3 will cause that word's previous value to be reused.
+ −
+ − A few notes regarding some bits in word0:
+ −
+ − ml_synchro (bit 0): the L1S code ORs a 1 into this bit in the NDB API word
+ − after it has loaded all of the words. It thus seems more correct to me to put
+ − a 0 in this bit in the files, so that the DSP sees the new descriptor when it
+ − is complete - but of course we can never know for sure without knowing what
+ − actually happens inside the DSP.
+ −
+ − ml_directF: both common sense and the TSM30 source (which uses the Melody E1
+ − feature of the DSP in that old Calypso version) suggest that ml_directF is
+ − bit 1, ml_square1 is bit 2 and ml_square2 is bit 3, i.e., it appears that the
+ − table on page 161 of L1M_AS001_1.pdf is wrong in this regard. Also note the
+ − order in which the fields are described on page 162 of the same PDF document.
+ −
+ − This is where our current knowledge ends. Until we either obtain a copy of the
+ − source for the DSP ROM or painstakingly reverse-engineer it, all we can do is
+ − look at the few existing examples of E1-format melodies we can find (see below)
+ − and experiment with putting different values in the various fields based on the
+ − description in the L1M_AS001_1.pdf document.
+ −
+ − Examples of E1-format melodies
+ − ==============================
+ −
+ − We've been very fortunate to discover that the legendary TSM30 phone appears to
+ − have used the Melody E1 feature, and that there are a bunch of E1-format
+ − melodies embedded in the famous TSM30 source from HispaPhreak. I have extracted
+ − these melodies, played them through the earpiece speaker on a Pirelli DP-L10
+ − phone running FreeCalypso Magnetite (our own FCDEV3B with a loudspeaker that we
+ − can actually use has not been built yet as of this writing), and found some of
+ − them to be quite pleasant-sounding. These extracted TSM30 melodies can be found
+ − here:
+ −
+ − ftp://ftp.freecalypso.org/pub/GSM/ringtone/tsm30-melody-e1.tar.gz
+ −
+ − I also found a couple of melodies in our TCS211 reference semi-src under
+ − chipsetsw/services/Audio/tests; these two melodies illustrate how one can load
+ − word2 and word3 the first time and then omit them afterward when reloading the
+ − same oscillator. (All of the TSM30 melodies always load all 4 words in every
+ − oscillator descriptor.)
+ −
+ − Our own ASCII format for E1 melodies
+ − ====================================
+ −
+ − In this FreeCalypso host tools package we have a utility for decoding existing
+ − Melody E1 binary bits into an amenable-to-study ASCII format, as well as a
+ − utility for generating new E1-format binary melodies from an ASCII text source
+ − in the same format. The ASCII format is of our own invention, and consists of
+ − numeric fields which map directly to the various bit fields in the DSP+fw's
+ − binary format.
+ −
+ − Our ASCII format for E1 melodies consists of 3 parts: an osc-set global header
+ − line, a sequence of time blocks, and an end line. The noteworthy aspects are:
+ −
+ − * Each time block is given as a time line followed by 0 or more osc lines.
+ − This lines must follow in direct succession without intervening blank or
+ − comment lines, and each time block must end with a blank line.
+ −
+ − * The end marker line is mandatory; having the ASCII file just end without it
+ − is an error.
+ −
+ − Please see the source code for fc-e1decode and fc-e1gen for the rest.
+ −
+ − Some words regarding Melody E2
+ − ==============================
+ −
+ − E1-format melodies are self-contained: if you have a valid binary melody file
+ − in E1 format from whatever source, you can play it through the DSP of any
+ − Calypso device that runs our TCS211-based Magnetite firmware. But it is not so
+ − simple with Melody E2. In order to play a melody in E2 format, one needs not
+ − only the melody file itself, but also the set of *.mwa (instrument wave) files
+ − corresponding to the set of instruments used by that melody. It appears that
+ − the melody group at TI had produced as many as 48 different instrument wave
+ − tables: see the list in the non-production
+ − #if (AUDIO_SIMULATION) || (AUDIO_L1_STANDALONE)
+ − section of the Cust_audio_melody_E2_load_instrument() function in l1audio_cust.c
+ − in both TSM30 and LoCosto/Peek sources. (The LoCosto version lists 48
+ − instruments whereas the much earlier TSM30 version lists only 40 of them, thus
+ − the list must have been added to over the course of TI history.) A given E2
+ − melody selects a subset of 1 to 8 instruments out of the larger set to be used
+ − in that melody, and these selected instrument waves are loaded into the DSP's
+ − API RAM before the actual play of the melody itself.
+ −
+ − Unfortunately all we have are the *.mwa file _names_ for the 48 Melody E2
+ − instruments that apparently existed at TI once upon a time, but not any of the
+ − actual bits. The TSM30 source uses only Melody E1, not E2, thus we do not
+ − currently have any source from which we can take any E2-format melody examples
+ − or E2 instrument wave tables for TI's DSP. We also don't have any documentation
+ − for any of these bits, and analysis of the Melody E2 code in L1 shows that it is
+ − significantly different from E1. The code in TCS211 L1 that reads Melody E2
+ − file bits is not of much help for making our own E2 melodies, as all of the real
+ − magic happens in the DSP, not on the ARM side.
+ −
+ − Thus our FreeCalypso hardware+firmware combination is capable of playing both E1
+ − and E2 melodies, but we won't be able to exercise the latter capability until
+ − and unless someone finds a surviving copy of some existing E2 melodies along
+ − with the *.mwa instrument wave files they require, whether it is the same
+ − instrument set as listed in the non-production section of l1audio_cust.c or a
+ − different one. But if someone does obtain a set of such melody bit files, our
+ − FreeCalypso devices running FreeCalypso firmware are ready to play them.