view doc/Melody_E1 @ 980:0a4d19aab608

PL129N lock-state cosmetic: 256 KiB blocks are single sectors
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 02 Dec 2023 04:31:58 +0000
parents e50c3aa1152a
children
line wrap: on
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.