RFC 2897
Proposal for an MGCP Advanced Audio Package
RFC 2897: Proposal for an MGCP Advanced Audio Package โจ
Title block (the important bits):
- Who wrote it: D. Cromwell from Nortel Networks, for the Network Working Group ๐
- Number: RFC 2897
- Category: Informational, so it's a proposal, not a standard ๐
- Date: August 2000
- Obsoletes / Updates: the title block lists neither, so it doesn't replace or update any other RFC ๐ซถ
Status of this Memo ๐
This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.
Copyright Notice ยฉ๏ธ
Copyright (C) The Internet Society (2000). All Rights Reserved.
Abstract ๐ธ
okay so this doc proposes a brand new event/signal package for MGCP (Media Gateway Control Protocol) ๐ The package controls an ARF (Audio Resource Function), which can live on a Media Gateway or on a specialized Audio Server. ๐ฅ
It handles the standard IVR (Interactive Voice Response) moves: PlayAnnouncement, PlayCollect, and PlayRecord ๐ง It can reference simple audio directly, or reference simple and complex audio indirectly. It also brings audio variables, control over whether audio can be interrupted, digit buffer control, special key sequences, and reprompting during data collection โจ
And it lets you define as many user-defined qualifiers as you want to resolve complex audio structures. Like, you could make qualifiers for any or all of these: language, accent, audio file format, gender, speaker, or customer. Main character energy ๐
Table of Contents ๐
1. Introduction ................................................ 2
1.1. Audio Segments ............................................ 3
1.1.1. Sequences And Sets ...................................... 3
1.1.2. Segment Types ........................................... 4
2. Advanced Audio Package ...................................... 5
3. Events ...................................................... 5
4. Event Parameters ............................................ 7
5. Return Parameters ........................................... 7
6. Variables ................................................... 14
7. Selectors ................................................... 17
8. Aliases ..................................................... 18
9. Examples .................................................... 21
10. Formal Syntax Description .................................. 22
11. References ................................................. 22
12. Formal Syntax Description .................................. 25
13. References ................................................. 32
14. Author's Address ........................................... 33
15. Full Copyright Statement ................................... 34
1. Introduction ๐ฆ
okay so this syntax handles both simple and complex audio structures ๐ถ A simple one is basically a single announcement, like "Welcome to Bell South's Automated Directory Assistance Service". A complex one is more like a bunch of pieces glued together: an announcement, then a voice variable, then another announcement. The example given is "There are thirty seven minutes remaining on your prepaid calling card," where "There are" is a prompt, the number of minutes is a voice variable, and "minutes remaining on your prepaid calling card" is another prompt ๐ง
It also gets extra spicy. Complex audio can be qualified by user-defined selectors like language, audio file format, gender, accent, customer, or voice talent ๐ So if that same example were qualified by language and accent, you could play "There are thirty seven minutes remaining on your prepaid calling card" in English with a southern accent, or in English with a mid-western accent, as long as someone had provisioned that audio ๐ซถ
There are two ways to specify complex audio ๐ The first is to directly reference each individual component. That needs a complete description of every component sent over the protocol. The second is to provision all the components on the Audio Server as one single entity, then export a reference to that entity to the call agent. With this approach, only the reference gets passed over the protocol (plus any dynamic data, like variable data), and you don't need to specify the individual components at all ๐ฅ
The Audio Server Package does a lot, and most of that is controlled by protocol parameters ๐ Most parameters are optional, and wherever possible they default to reasonable values. So an audio app that references provisioned, complex audio structures and takes advantage of optionality and defaults can specify audio events with a minimum of syntax. Iconic efficiency ๐ญ
1.1. Background ๐
The next two sections have background info that might help you understand the syntax โจ
1.1.1. Sequence And Sets ๐
okay so the syntax supports abstractions of set and sequence for storing and referencing audio data ๐
A sequence is a provisioned run of one or more audio segments. The component segments don't all have to be the same type. Every sequence gets a unique segment id. On playback, a sequence id reference gets broken down into its individual parts, and each part plays in order ๐ต
A set is a provisioned collection of audio segments with an associated selector. On playback, the selector value resolves to one particular set element. Selector types are supported by the syntax, but the syntax doesn't define individual selector types, except for the predefined language selector. Instead, the user (aka the provisioner) defines them. A user could define one or more of these selector types: language, accent, audio file format, gender, accent, customer, or day of the week. For each selector type, the user must define a range of valid values. The user may also choose a default value. At runtime, if no selector value is supplied, the default value gets used ๐
Here's an example. Say an app plays a prompt in English, French, or Russian. The provisioner defines a set with the predefined selector "Lang", and defines three possible values for it: "eng", "fra", and "rus". Then they provision three recordings of the prompt, one per language, and link the French recording to the "fra" selector value, and so on. The provisioner can also set a default selector value for when none is supplied, like "eng". The whole set gets its own unique segment id ๐ง
At runtime, a reference to the set with the selector set to "rus" plays the Russian prompt. A reference to the set with no selector plays the English prompt, since English was set as the default selector value ๐ธ
Nested definition of sets and sequences is allowed, meaning a set of sets or a sequence of sequences is legal. You can also mix sets and sequences together, so a set of sequences or a sequence containing one or more set elements is fine too. Direct or transitive definition of a set or segment in terms of itself is not allowed ๐
1.1.2. Segment Types ๐ฆ
The syntax supports these segment types:
RECORDING: a reference, by unique id, to a single piece of recorded audio. RECORDINGs can be provisioned, or they can be made during a call. A RECORDING made during a call can be temporary or persistent. A temporary RECORDING lasts only for the life of the call it was recorded in. A persistent RECORDING lasts beyond the life of that call ๐
A provisioned RECORDING can be replaced (or overridden) by a persistent RECORDING. A reference to the provisioned RECORDING's id then resolves to the persistent one. The overriding persistent audio can later be deleted, and the original provisioned audio can be restored ๐ฅ
A provisioned RECORDING can be overridden more than once. In that case, the provisioned RECORDING's id refers to the latest overriding RECORDING. When that overriding RECORDING gets deleted, the original provisioned RECORDING is restored, even if the segment was overridden multiple times ๐
TEXT: a reference to a block of text to be converted to speech or displayed on a device. You can reference it by unique id to a block of provisioned text, or specify the text directly in a parameter ๐SILENCE: a length of silence to play, in units of 100 milliseconds โจTONE: a tone to play through algorithmic generation. Most tones will probably be recorded instead of generated. Exact specification of this segment type is tbd ๐VARIABLE: a voice variable, specified by the parameters type, subtype, and value. Variables get covered in more detail in a later section of this document ๐งSEQUENCE: a reference, by unique id, to a provisioned sequence of mixed RECORDING, TEXT, SILENCE, TONE, VARIABLE, SET, or SEQUENCE segments. Nested definition of SEQUENCE segments is allowed. Direct or transitive definition of a SEQUENCE segment in terms of itself is not allowed ๐SET: a reference, by unique id, to a provisioned set of segments. The intended and recommended use of the SET type is that all segments in the set are semantically equivalent. There's no real way to enforce that, though, either in the protocol or in provisioning ๐ซถ Every set has an associated selector, which resolves the set reference to one specific element at runtime. The elements of a set can be any of these segment types: RECORDING, TEXT, TONE, SILENCE, SEQUENCE, or SET. The protocol doesn't specify selector types, so the user has to define them. Nested definition of SET segments is allowed. Direct or transitive definition of a SET segment in terms of itself is not allowed ๐
2. Advanced Audio Package ๐ง
Package Name: AU
This package defines events and signals for an ARF package for an Audio Server Media Gateway ๐ฅ
3. Events ๐
okay so here's the event table. Each row is a symbol, its definition, and the R and S columns with the duration ๐
______________________________________________________________________
| Symbol | Definition | R | S Duration |
|______________|________________________|______|______________________|
| pa(parms) | PlayAnnouncement | | TO variable |
| pc(parms) | PlayCollect | | TO variable |
| pr(parms) | PlayRecord | | TO variable |
| es(parm) | EndSignal | | BR |
| oc(parms) | OperationComplete | x | |
| of(parms) | OperationFailed | x | |
Okay so, the events are where it gets juicy ๐
- PlayAnnouncement: Plays an announcement when the user doesn't need to interact with anything ๐. Since there's no need to keep an eye on the incoming media stream, this is a super efficient way to handle treatments, informational announcements, etc. ๐ข
- PlayCollect: Plays a prompt and collects DTMF digits from a user ๐ข. If no digits come in, or the digit pattern is invalid, the user may be reprompted and given another shot at entering a correct pattern ๐ซถ. The supported digits are
0-9,*,#,A,B,C,Dโจ. By default PlayCollect doesn't play an initial prompt and only makes one attempt to collect digits, so it basically works like a plain Collect operation ๐. You can also define various special purpose keys, key sequences, and key sets to use during a PlayCollect operation ๐. - PlayRecord: Plays a prompt and records what the user says ๐๏ธ. If the user doesn't speak, they may be reprompted and given another chance to record ๐. By default PlayRecord doesn't play an initial prompt and only makes one attempt to record, so it functions as a simple Record operation ๐ฆ.
- OperationComplete: Detected when a Play, PlayRecord, or Play Collect signal finishes successfully ๐ฅณ.
- OperationFailed: Detected when a Play, PlayRecord, or PlayCollect signal fails ๐ญ.
- EndSignal: Gracefully wraps up a Play, PlayCollect, or PlayRecord signal ๐ง. When a signal gets ended with EndSignal, the OperationComplete or OperationFailed event that follows still carries every parameter it normally would, including any collected digits or the recording id of the recording that was in progress when EndSignal arrived ๐.
4. Signal Interactions โจ
So here's the drama ๐. If an Advanced Audio Package signal is already active on an endpoint and another signal of the same type shows up, the two signals get compared, parameters and parameter values included ๐. If they're identical, the signal already in progress keeps going and the new one gets tossed ๐๏ธ. Because of that behavior, the Advanced Audio Package may not play nicely with some other packages, like the Line and Trunk packages ๐ฌ.
5. Parameters ๐
Okay, this part's giving organization ๐. The PlayAnnouncement, PlayRecord, and PlayCollect events can each be qualified by a string of parameters, and most of them are optional ๐ธ. Where it makes sense, parameters fall back to reasonable default values ๐ . PlayAnnouncement is the only event with a required parameter ๐. If a Play-Announcement event doesn't come with a parameter that specifies some form of playable audio, an error gets returned to the application ๐.
These parameters are laid out in the following table ๐ฆ:
_______________________________________________________________________
| Parameters |
|______________________________________________________________________|
| Symbol | Definition | pl | pc | pr |
|___________|_________________________________|________|________|______|
| an | announcement | x | | |
| ip | initial prompt | | x | x |
| rp | reprompt | | x | x |
| nd | no digits reprompt | | x | |
| ns | no speech reprompt | | | x |
| fa | failure announcement | | x | x |
| sa | success announcement | | x | x |
| ni | non-interruptible play | | x | x |
| it | iterations | x | | |
| iv | interval | x | | |
| du | duration | x | | |
| sp | speed | x | x | x |
| vl | volume | x | x | x |
| cb | clear digit buffer | | x | x |
| mx | maximum # of digits | | x | |
| mn | minimum # of digits | | x | |
| dp | digit pattern | | x | |
| fdt | first digit timer | | x | |
| idt | inter digit timer | | x | |
| edt | extra digit timer | | x | |
| prt | pre-speech timer | | | x |
| pst | post-speech timer | | | x |
| rlt | total recording length timer | | | x |
| rsk | restart key | | x | x |
| rik | reinput key | | x | x |
| rtk | return key | | x | x |
| psk | position key | | x | x |
| stk | stop key | | x | x |
| sik | start input key | | x | |
| eik | end input key | | x | x |
| iek | include end input key | | x | |
| na | number of attempts | | x | x |
|___________|_________________________________|________|________|______|
Okay so bestie, here are the parameters for the Advanced Audio Package events ๐ Each one is a little knob you can turn to control how the audio behaves ๐
Announcement: This is the audio to be played! It's made up of one or more audio segments ๐
Initial Prompt: This is the first announcement that asks the user to either punch in DTMF digits or start talking ๐ค It's one or more audio segments too. If you don't specify it (that's the default), the event starts collecting digits or recording right away โจ
Reprompt: This one plays after the user messes up, like typing an invalid digit pattern or not speaking at all ๐ It's one or more audio segments, and it defaults to the Initial Prompt ๐ซถ
No Digits Reprompt: Plays after the user fails to enter a valid digit pattern during a PlayCollect event ๐ It's one or more audio segments and defaults to the Reprompt ๐ธ
No Speech Reprompt: Plays after the user fails to speak during a PlayRecord event ๐๏ธ It's one or more audio segments and defaults to the Reprompt ๐
Failure Announcement: Played when every single data entry attempt has failed ๐ญ It's one or more audio segments, and there's no default ๐ฆ
Success Announcement: Played when data collection has succeeded ๐ It's one or more audio segments, and there's no default โจ
Non-Interruptible Play: If this is set to true, the initial prompt can't be interrupted by voice or digits ๐ซ It defaults to false. The only valid values are the text strings "true" and "false" ๐
Iterations: This is the maximum number of times an announcement gets played ๐ A value of minus one (-1) means it repeats forever, no cap ๐ It defaults to one (1).
Interval: This is the silence inserted between iterative plays ๐คซ It's specified in units of 100 milliseconds and defaults to 10 (1 second) ๐
Duration: This is the maximum amount of time to play, and possibly replay, an announcement โฐ It takes precedence over Iterations and Interval, so it wins ๐ It's specified in units of 100 milliseconds and has no default.
Speed: This is the relative playback speed of the announcement, given as a positive or negative percentage of the original playback speed ๐โโ๏ธ๐จ
Volume: This is the relative playback volume of the announcement, given as a positive or negative decibel variation from the original playback volume ๐โจ
Clear Digit Buffer: If set to true, this clears the digit buffer before the initial prompt plays ๐งน It defaults to false. The only valid values are the text strings "true" and "false" ๐
Maximum # Of Digits: This is the maximum number of digits to collect ๐ข It defaults to one (1). Don't specify this parameter if the Digit Pattern parameter is present ๐
โโ๏ธ
Minimum # Of Digits: This is the minimum number of digits to collect ๐ข It defaults to one (1). Don't specify this parameter if the Digit Pattern parameter is present ๐
โโ๏ธ
Digit Pattern: This is a legal digit map, as described in section 7.1.14 of the Megaco protocol [6], using the DTMF mappings associated with the Megaco DTMF Detection Package described in the Megaco protocol document [6] ๐บ๏ธ Don't specify this parameter if one or both of the Minimum # Of Digits parameter and the Maximum Number Of Digits parameter is present ๐ฅน
First Digit Timer: This is the amount of time the user has to enter the first digit โณ It's specified in units of 100 milliseconds, and the value is 50 (5 seconds) ๐
Inter Digit Timer: This is the amount of time the user has to enter each subsequent digit ๐ซง It's specified in units of 100 milliseconds and defaults to 30 (3 seconds) ๐ง
Extra Digit Timer: This is the amount of time to wait for the user to enter a final digit once the maximum expected number of digits has been entered ๐ฏ Typically this timer is used to wait for a terminating key in applications where a specific key has been defined to end input ๐ It's specified in units of 100 milliseconds. If it isn't specified, this timer isn't activated ๐
Pre-speech Timer: This is the amount of time to wait for the user to initially speak ๐ฃ๏ธ It's specified in units of 100 milliseconds and defaults to 30 (3 seconds) โญ
Post-speech Timer: This is the amount of silence needed after the end of the last speech segment for the recording to count as complete ๐ค It's specified in units of 100 milliseconds and defaults to 20 (2 seconds) ๐
Recording Length Timer: This is the maximum allowable length of the recording, not including any pre- or post-speech silence ๐๏ธ It's specified in units of 100 milliseconds. This parameter is mandatory, no exceptions ๐จ
Restart Key: This defines a key sequence made of a command key, optionally followed by zero or more keys ๐ Its action is to discard any digits collected or any recording in progress, replay the prompt, and resume digit collection or recording ๐ There's no default. If an application defines more than one command key sequence, it'll typically use the same command key for all of them ๐ And if more than one command key sequence is defined, then every key sequence has to consist of a command key plus at least one other key ๐
Reinput Key: This defines a key sequence made of a command key, optionally followed by zero or more keys ๐ Its action is to discard any digits collected or any recordings in progress, and then resume digit collection or recording ๐ซถ There's no default. Same deal as before: an application with more than one command key sequence will typically use the same command key for all of them, and if more than one is defined, every key sequence must be a command key plus at least one other key ๐
Return Key: This defines a key sequence made of a command key, optionally followed by zero or more keys ๐ Its action is to terminate the current event and any queued event, and to return the terminating key sequence to the call processing agent ๐ There's no default. Once again, an application that defines more than one command key sequence will typically use the same command key for all of them, and if more than one is defined, every key sequence has to be a command key plus at least one other key โจ
Position Key: This defines a key with the following action ๐ฎ It stops playing the current announcement and resumes playing at the beginning of the first, last, previous, next, or current segment of the announcement โชโฉ There's no default. The actions for the position key are fst, lst, prv, nxt, and cur ๐งฉ
Stop Key: This defines a key with the following action ๐ It terminates playback of the announcement. There's no default ๐
Start Input Keys: This defines a set of keys that are acceptable as the first digit collected ๐น This set of keys can be specified either to interrupt a playing announcement or to not interrupt one ๐
The default key set is 0-9 ๐ The default behavior is to interrupt a playing announcement when a Start Input Key is pressed โก This behavior can be overridden for the initial prompt only, by using the ni (Non-Interruptible Play) parameter ๐ The specification is a list of keys with no separators, for example 123456789# ๐
End Input Key: This specifies a key that signals the end of digit collection or voice recording ๐ The default end input key is the # key. If you want no End Input Key to be used, set the parameter to the string "null" ๐
โโ๏ธ By default, the End Input Key isn't returned in the digits sent back to the call agent ๐คซ That behavior can be overridden by the Include End Input Key (eik) parameter ๐ฆ
Include End Input Key: By default, the End Input Key is not included in the collected digits returned to the call agent ๐ญ If this parameter is set to "true", then the End Input Key will be returned along with the collected digits ๐ The default is "false" ๐ธ
Number Of Attempts: This is the number of attempts the user needed to enter a valid digit pattern or to make a recording ๐ It defaults to 1. It's also used as a return parameter to show the number of attempts the user made ๐
Record Persistent Audio: If set to true, the recording that gets made is persistent instead of temporary ๐พ It defaults to false. The only valid values are the text strings "true" and "false" ๐ซถ
Delete Persistent Audio: This indicates that the specified persistent audio segment is to be deleted ๐๏ธ This parameter is carried by the PlayRecord event, although nothing gets played or recorded in this case ๐งน
Override Audio: This indicates that the specified provisioned audio segment is to be overridden with a persistent audio segment, which gets recorded during the PlayRecord operation that carries this parameter ๐๏ธโจ
Restore Audio: This indicates that the provisioned audio segment originally associated with the specified segment id is to be restored, and that the overriding persistent audio is to be deleted ๐ This parameter is carried by the PlayRecord event, although nothing gets played or recorded in this case ๐ฆ
6. Return Parameters โจ
Each event has its own set of possible return parameters ๐ They're listed in the tables below, so take a peek ๐
________________________________________________________________________
| Return Parameters |
|_______________________________________________________________________|
| Symbol | Definition | pl | pc | pr |
|___________|________________________________|________|_________|_______|
| vi | voice interrupt | | | x |
| ik | interrupting key sequence | | x | |
| ap | amount played | | x | x |
| na | number of attempts | | x | x |
| dc | digits collected | | x | |
| ri | recording id | | | x |
| rc | return code | x | x | x |
Okay bestie, let's get into the juicy bits ๐ โจ
Voice Interrupted: ๐ค This gets set to "true" if the initial prompt of a PlayRecord operation got interrupted by voice. If nothing interrupted it, it defaults to "false" ๐
Interrupting Key Sequence: ๐ข This is the key or key sequence that cut off the initial prompt of a PlayCollect. You write it using the digit map characters "0" through "9" and "A" through "F", as defined in the DTMF Detection Package in the Megaco protocol document [6]. Very precise, very iconic ๐
Amount Played: โฑ๏ธ This is how much of the initial prompt got played before it was interrupted, measured in 100 ms units. Tiny clock, big energy โญ
Number Of Attempts: ๐ This counts how many tries the user needed to enter a valid digit pattern or make a recording. It defaults to 1, so she's a first-try queen unless told otherwise ๐. It's also an input parameter, so you can use it to set how many attempts the user gets to be allowed to enter a valid digit pattern or make a recording. Main character planning ๐ง
Digits Collected: ๐ These are the DTMF digits collected during a PlayCollect operation, again using the digit map characters "0" through "9" and "A" through "F" as defined in the DTMF Detection Package in the Megaco protocol document [6]. Bestie, the detail is everything ๐ซถ
Recording ID: ๐๏ธ This is a 32 bit binary integer assigned to audio recorded during the Play Record operation. It's basically the recording's little name tag ๐ท๏ธ๐ฆ
Return Code: ๐ฆ This is a return code that gives the final status of the operation. There are two ranges defined, and they're giving clear vibes:
_________________________________
| Range | Meaning |
|________|_______________________|
|100-199 | successful completion |
|300-399 | error |
|________|_______________________|
The following return codes are define:
________________________________________________________________________
|Return Code | Meaning |
|____________|__________________________________________________________|
| 100 | Success |
| 300 | Unspecified failure |
| 301 | Bad audio ID |
| 302 | Bad selector type |
| 303 | Bad selector value |
| 304 | Variable type not supported |
| 305 | Variable subtype not supported |
| 306 | Invalid variable name |
| 307 | Variable value out of range |
| 308 | Inconsistent variable specification |
| 309 | Alias not found |
| 310 | Extra sequence data |
| 311 | Missing sequence data |
| 312 | Mismatch between play specification and provisioned data |
| 313 | Language not set |
| 314 | Remove override error |
| 315 | Override error |
| 316 | Delete audio error |
| 317 | Unable to record temporary audio |
| 318 | Unable to delete temporary audio |
| 319 | Unable to record persistent audio |
| 320 | Unable to delete persistent audio |
| 321 | Unable to override non-existent segment id |
| 322 | Unable to remove override from non-existent segment id |
| 323 | Provisioning error |
| 324 | Unspecified hardware failure |
| 325 | Syntax error |
| 326 | No digits |
| 327 | No speech |
| 328 | Spoke too long |
| 329 | Digit pattern not matched |
| 330 | Max attempts exceeded |
|____________|__________________________________________________________|
Here are some examples of how the return parameters get used, and they're so satisfying to read ๐ฅน
The PlayAnnouncement event completed successfully โ :
O: AU/oc(rc=100)
The PlayAnnouncement event failed because an alias wasn't found ๐:
O: AU/of(rc=309)
The PlayCollect event completed successfully on the user's second attempt when the user entered the digits 04375182 ๐ขโจ:
O: AU/oc(rc=100 na=2 dc=04375182)
The PlayRecord event was successful on the user's first attempt, and the id of the recording the user made is 983 ๐๏ธ:
O: AU/oc(rc=100 na=1 ri=983)
7. Segment Descriptors ๐งฉ
Okay so segment descriptors are used with the an, ip, rp, nd, ns, fa, and sa parameters. Their whole job is to define the segments that make up an announcement, and honestly they're the building blocks of the whole look ๐งฑ๐
________________________________________________________________________
| Segment Descriptors |
|_______________________________________________________________________|
| Symbol | Definition |
|____________________________________|__________________________________|
| 32 bit binary number | segment identifier |
| ts | text to speech |
| dt | display text |
| si | silence |
| to | tone |
| vb | variable |
|____________________________________|__________________________________|
Segment Identifier: ๐ This is a 32 bit binary integer that identifies a provisioned entity, like a recording, set, sequence, and so on ๐
Text To Speech: ๐ฃ๏ธ This specifies a text string to be converted to speech. Hello robot voice, it's giving narrator ๐ง
Display Text: ๐บ This specifies a text string to be displayed on a device. Words on a screen, no cap ๐
Silence: ๐คซ This specifies a length of silence to be played, in units of 100 milliseconds. Quiet, but make it intentional ๐
Tone: ๐ถ This specifies a tone to be played by algorithmic generation. The exact specification of this parameter is tbd, which means still to be decided ๐. Most tones will likely be recorded, not generated, so don't stress about it ๐ฆ
Variable: ๐ฎ This specifies a voice variable by type, subtype, and value. Variables get a much fuller explanation in the next section, so keep scrolling bestie ๐
8. Variables ๐
Okay the syntax supports two kinds of variables, and they're both iconic in their own way ๐. Embedded variables are variables that have been provisioned as part of a segment. Standalone variables are completely specified in the protocol message.
Typically embedded variables get provisioned along with recorded speech, like "A representative will be with you in approximately 5 minutes. If you would prefer to leave a voice message, press 1 now", where the variable is the number of minutes. This is the kind of variable people often call an embedded variable ๐ซถ
Variables are specified by the following parameters: type, subtype, and value. Variable types include Date, Money, Number, Time, and so on โฐ๐ธ. The subtype is a refinement of the type. For example, the variable type Money might have a range of subtypes like Dollar, Rupee, Dinar, etc. ๐ช Not all variables need a subtype, and for those, the subtype parameter should be set to null ๐ โโ๏ธ.
For embedded variables, the type and subtype must be provisioned. The value may be provisioned too. If it isn't provisioned, it must be specified as part of the variable reference. In a list of segments, an embedded variable value specification only applies to the segment that directly precedes it. If a segment has multiple embedded variables, the values must be given in the order they're encountered when the segment is played. Order matters, bestie ๐โจ
Here are some examples, because examples are everything ๐ฅฐ
A standalone variable:
S: pa(an=vb(mny,usd,1153))
An embedded variable:
S: pa(an=37<1153>)
Not all variables, like the date variable in the next example, need a subtype. In that case, the subtype is encoded with the value "null" ๐ :
S: pa(an=vb(dat,null,101598))
Sometimes you want to play an announcement that has an embedded variable without actually playing the variable itself ๐ค. To do that, a single "null" is provided for the value:
S: pa(an=37<null>)
Last but not least, here's the variable qualifiers table, which is basically the cheat sheet for everything above ๐๐
________________________________________________________________________
| Variables Qualifiers |
|_______________________________________________________________________|
| Symbol | Definition | Type | Subtype | Subtype Of |
|_________|__________________________|________|___________|_____________|
| dat | date | x | | |
| dig | digits | x | | |
| gen | generic | | x | dig |
| ndn | North American DN | | x | dig |
| dur | duration | x | | |
| mth | month | x | | |
| mny | money | x | | |
| num | number | x | | |
| crd | cardinal | | x | nm |
| ord | ordinal | | x | nm |
| sil | silence | x | | |
| str | string | x | | |
| txt | text | x | | |
| dsp | display text | | x | txt |
| spk | text to speech | | x | txt |
| tme | time | x | | |
| t12 | twelve hour format | | x | tme |
| t24 | twenty four hour format | | x | tme |
| ton | tone | x | | |
| wkd | weekday | x | | |
Okay bestie, the variables section is wrapping up ๐ Here's the bottom of that table, which is giving very organised energy โจ
|_________|__________________________|________|___________|_____________|
Date: Speaks a date written as YYYYMMDD, following ISO 8601, International Date and Time Notation [7]. So 19981015 gets spoken as "October fifteenth nineteen ninety eight" ๐
๐
Digits: Speaks a string of digits one at a time ๐ข If the subtype is North American DN (the format is NPA-NXX-XXXX), the digits get appropriate pauses between the NPA and NXX and between the NXX and XXXX. If the subtype is generic, the digits are spoken with no pauses at all. Iconic ๐
Duration: Duration is given in seconds and gets spoken in one or more units of time as needed. For example, 3661 is spoken as "One hour, one minute, and one second" โฐ๐ฆ
Money: Money is given in the smallest unit of a currency and gets spoken in one or more units of currency as needed. For example, 110 in U.S. Dollars is spoken "one dollar and ten cents" ๐ธ The three letter codes from ISO 4217, Currency And Funds Code List [5], are used to pick the currency subtype. Here's a small excerpt from ISO 4217, lowkey a fun little list ๐
__________________________________________________________
|Alpha-code | Numeric-code | Currency | Entity |
|___________|______________|__________|___________________|
|GQE | 226 | Ekwele | Equatorial Guinea |
|GRD | 300 | Drachma | Greece |
|GTQ | 320 | Quetzal | Guatemala |
|___________|______________|__________|___________________|
Money can also be negative or positive ๐ค In the example above, -110 is spoken as "minus one dollar and ten cents" ๐
Month: Speaks the specified month, so 10 is spoken as "October" ๐ It's given in MM format, with "01" meaning January, "02" meaning February, and so on. The calendar is serving ๐
Number: Speaks a number in cardinal or ordinal form. For example, 100 is spoken as "one hundred" in cardinal form and "one hundredth" in ordinal form ๐ฅ Cardinal numbers can be negative or positive. Math girlies, this one's for you ๐งฎ
Silence: Plays a set period of silence ๐คซ It's specified in 100 millisecond units. Quiet, but make it chic ๐ฆข
String: Speaks each character in a string, so a34bc is spoken "A, three, four, b, c" ๐ง Valid characters are a-z, A-Z, 0-9, #, and *. Very precise, very obsessed ๐ซถ
Text: Produces the specified text as speech, or displays it on a device ๐ฑโจ
Time: Speaks a time in either twelve hour format or twenty four hour format, depending on the subtype ๐ For example, 1700 is spoken as "Five pm" in twelve hour format, or as "Seventeen hundred hours" in twenty four hour format. It's specified in HHMM format per ISO 8601, International Data and Time Notation [7].
Tone: Plays an algorithmically generated tone. Exactly what that looks like is tbd ๐ถ Most applications will probably just use prerecorded tones, which is honestly the move ๐ง
Weekday: Speaks the day of the week, like "Monday" ๐ธ Weekdays are given as single digits, with "1" meaning Sunday, "2" meaning Monday, and so on. It's giving calendar math ๐๏ธ
9. Selectors โจ
Selector types are definable by the user, except for the predefined "Lang" (language) selector ๐ A selector can be applied to an individual segment within an operation, or to all the segments in an operation. For each selector type, the user must also define a range of values the selector can take ๐
For example, if the user defines a selector of type "phase-of-the-moon", they might also define the legal values as "new", "half", "full", "harvest", and "blue" ๐ For the selector to actually work at runtime, audio for each selector value must be provisioned. Real setup, real commitment ๐ซถ
Although it's not required, it is suggested that the three letter codes from ISO standard 639-2, Code For The Representation Of Names Of Languages [4], be used as values for user defined language selectors ๐ Here's a small excerpt from ISO 639-2:
_________________
|Code | Language |
|_____|__________|
|cze | Czech |
|cym | Welsh |
|dan | Danish |
|_____|__________|
Selectors can apply to entire operations or to a single segment within an operation. If an operation has multiple segments, each segment may have its own set of selectors. If both segment selectors and operation selectors are present, the segment selector takes precedence for that segment ๐ The operation selectors apply to all segments in that operation that don't have their own segment selectors. If a selector set isn't specified, the provisioned defaults are used.
Selectors are only applied to variables after the variable has been resolved. For instance, if a date variable resolved to "October 15th, 1998", the voice it's spoken with could resolve to either male or female, if a gender selector had been defined ๐
10. Aliases ๐ฆ
Aliasing of audio segments is supported ๐ง The alias to segment id mapping is provisioned, and at runtime the alias is resolved to its associated segment id. The syntax for an alias is the alias wrapped between two forward slashes, like this:
S: pa(an=/not-in-service/)
11. Examples ๐
This section shows a bunch of examples of how the syntax gets used, and they are so cute ๐ฅน Arguments to an event are separated by one or more whitespace characters, which can be either an ASCII space character or an ASCII tabulation character. Spacing matters, bestie ๐
Play an announcement that's a single segment:
S: pa(an=39)
Play an announcement made of multiple segments:
S: pa(an=39,40,47)
Play an announcement that's a recording, then silence, then text to speech, then a standalone voice variable ๐๏ธ
S: pa(an=39 si(30) ts(hello) vb(my,usd,3999))
Play an announcement with an embedded variable. If the first three segments of the previous announcement were provisioned as segment 40, the following is exactly equivalent to the play in the example above ๐ซถ
S: pa(an=40<3999>)
Play an announcement with two embedded variables ๐
S: pa(an=113<3999,10151998>)
Play a prompt and collect a single digit. If needed, play a reprompt, a no digits prompt, and a success or failure announcement. Give the user three attempts to enter a digit ๐ข
S: pc(ip=21 rp=109 nd=102 fa=81 sa=72 na=3)
Play a prompt and collect a single digit. If the user doesn't enter a digit, replay the initial prompt. Give the user three attempts to enter a digit ๐ธ
S: pc(ip=21 na=3)
Play a prompt and record voice. If the user doesn't speak, play a no speech prompt. Give the user two attempts to record ๐ค
S: pr(ip=22 ns=42 na=2)
Play an announcement at ninety percent of its original speed and five decibels softer than its original volume. Play the announcement three times, with two seconds of silence between plays ๐
S: pa(an=27 sp=90 vl=-5 it=3 iv=20)
Give the user two attempts to enter a three digit pattern. Clear the digit buffer before playing the prompt. The user can signal the end of input with the # key, which is not returned to the call agent with the collected digits ๐
S: pc(ip=43 cb=true mn=3 mx=3 na=2)
Give the user three attempts to enter a three digit pattern. If the user enters one digits or two digits on the first or second attempts, a reprompt is played. If the user enters no digits on the first or second attempts, a no digits reprompt is played. If all three attempts fail, a failure announcement is played. If one of the attempts succeeds, a success announcement is played and the collected digits are returned to the call agent. The user can signal the end of input with the # key. If the # key ends a successful input attempt, the collected digits, but not the # key, are returned to the call agent ๐
S: pc(ip=87 rp=5 nd=409 fa=9 sa=18 mx=3 na=3)
Give the user a single attempt to enter a a 1 to 4 digit pattern. Allow 8 seconds for the user to enter the first digit, and 6 seconds for each subsequent digit. If the subsequent digit timer expires after the user has fewer than four digits, the collected digits are returned to the call agent. The user can signal the end of input with the # key, which is not returned to the call agent with the collected digits โณ
S: pc(ip=4 fdt=80 idt=60 mx=4)
Give the user three chances to enter an 11 digit number that begins with 0 or 1. If the user makes a mistake while entering digits, they can press the * key to discard any digits already collected, replay the prompt, and resume collection ๐งน
S: pc(ip=33 mn=11 mx=11 sik=01 rsk=* na=3)
Give the user three chances to enter an 11 digit number that begins with 0 or 1. If the user makes a mistake while entering digits, they can press the key sequence *11 to discard any digits already collected, replay the prompt, and resume collection. If the user enters the key sequence *12, the play collect is terminated along with any queued events, and the terminating key sequence is returned to the call agent for processing ๐
S: pc(ip=33 mn=11 mx=11 sik=01 rsk=*11 rtk=*12 na=3)
Give the user two chances to make a recording. After playing the prompt, wait 5 seconds for the user to speak. Otherwise, replay the initial prompt and try again. If the user does speak, wait seven seconds after speech stops to make sure they're finished. If the recording is successful, return a reference to the recording to the call agent ๐ฌ
S: pr(ip=6 prt=50 pst=70 na=2)
Play an announcement in the default language:
S: pa(an=5)
Play the same announcement in English. In the first example, the selector applies to the an segment; in the second, it applies to the pa operation. For these particular examples, the net effect is the same ๐ฌ๐ง
S: pa(an=5[Lang=eng]) or S: pa(an=5)[Lang=eng]
Play an announcement in Danish using a female voice with a Cajun accent ๐ง
S: pa(an=6)[Lang=dan,gender=female,accent=cajun]
Play the first part of an announcement in English, the second part in the default language, and the third part in French ๐ฅ
S: pa(an=5[Lang=eng],6,7[Language=fra])
Play an announcement with an embedded variable in English:
S: pa(an=5<101599>)[Lang=eng]
12. Formal Syntax Description ๐
Here's the formal syntax, which is giving pure grammar energy ๐ค
AudPkgEvent = PlayAnnouncement / PlayCollect / PlayRecord /
OperationComplete / OperationFailed / EndSignal
PlayAnnouncement = [ AdvAudioPkgToken SLASH ] PlayAnnToken
LPAREN PlayAnnParmList RPAREN [ OpSelectorList ]
PlayCollect = [ AdvAudioPkgToken SLASH ] PlayColToken
LPAREN [ PlayColParmList ] RPAREN [ OpSelectorList ]
PlayRecord = [ AdvAudioPkgToken SLASH ] PlayRecToken
LPAREN [ PlayRecParmList ] RPAREN [ OpSelectorList ]
OperationComplete = [ AdvAudioPkgToken SLASH ] OpCompleteToken
LPAREN OpCompleteParmList RPAREN
OperationFailed = [ AdvAudioPkgToken SLASH ] OpFailedToken
LPAREN ReturnCodeParm RPAREN
EndSignal = [ AdvAudioPkgToken SLASH ] EndSignalToken
LPAREN SignalParm RPAREN
OpSelectorList = LSQUARE OpSelector *( COMMA OpSelector ) RSQUARE
OpSelector = NAME EQUALS NAME
PlayAnnParmList = PlayAnnParm *( WSP PlayAnnParm )
Okay bestie, we're picking up right where the parameter lists left off ๐
PlayColParmList = PlayColParm *( WSP PlayColParm )
PlayRecParmList = PlayRecParm *( WSP PlayRecParm )
OpCompleteParmList = OpCompleteParm *( WSP OpCompleteParm )
PlayAnnParm = ( AnnouncementParm / IterationsParm / IntervalParm /
DurationParm / SpeedParm / VolumeParm )
PlayColParm = ( InitPromptParm / RepromptParm / NoDigitsParm /
FailAnnParm / SuccessAnnParm / NoInterruptParm /
SpeedParm / VolumeParm / ClearBufferParm /
MaxDigitsParm / MinDigitsParm / DigitPatternParm /
FirstDigitParm / InterDigitParm / ExtraDigitParm /
RestartKeyParm / ReinputKeyParm / ReturnKeyParm /
PosKeyParm / StopKeyParm / StartInputKeyParm /
EndInputKeyParm / IncludeEndInputKey /
NumAttemptsParm )
PlayRecParm = ( InitPromptParm / RepromptParm / NoSpeechParm /
FailAnnParm / SuccessAnnParm / NoInterruptParm /
SpeedParm / VolumeParm / ClearBufferParm /
PreSpeechParm / PostSpeechParm / RecordLenParm /
RestartKeyParm / ReinputKeyParm / ReturnKeyParm /
PosKeyParm / StopKeyParm / EndInputKeyParm /
RecPersistParm / OverrideAudioParm /
RestoreAudioParm / DeletePersistParm /
NumAttemptsParm )
OpCompleteParm = ( VoiceInterruptParm / IntKeySeqParm /
NumAttemptsParm / AmtPlayedParm / DigitsColParm /
RecordingIdParm / ReturnCodeParm )
AnnouncementParm = AnParmToken EQUALS Segmentlist
InitPromptParm = IpParmToken EQUALS Segmentlist
RepromptParm = RpParmToken EQUALS Segmentlist
NoDigitsParm = NdParmToken EQUALS Segmentlist
NoSpeechParm = NsParmToken EQUALS Segmentlist
FailAnnParm = FaParmToken EQUALS Segmentlist
SuccessAnnParm = SaParmToken EQUALS Segmentlist
DurationParm = DuParmToken EQUALS NUMBER
IterationsParm = ItParmToken EQUALS ( NUMBER / "-1" )
IntervalParm = IvParmToken EQUALS NUMBER
SpeedParm = SpParmToken EQUALS SIGNEDINT
VolumeParm = VlParmToken EQUALS SIGNEDINT
NoInterruptParm = NiParmToken EQUALS BOOLSTR
ClearBufferParm = CbParmToken EQUALS BOOLSTR
MaxDigitsParm = MxParmToken EQUALS NUMBER
MinDigitsParm = MnParmToken EQUALS NUMBER
DigitPatternParm = DpParmToken EQUALS DIGITPATTERN
FirstDigitParm = FdtParmToken EQUALS NUMBER
InterDigitParm = IdtParmToken EQUALS NUMBER
ExtraDigitParm = EdtParmToken EQUALS NUMBER
PreSpeechParm = PrtParmToken EQUALS NUMBER
PostSpeechParm = PstParmToken EQUALS NUMBER
RecordLenParm = RltParmToken EQUALS NUMBER
RestartKeyParm = RskParmToken EQUALS CommandKeySequence
ReinputKeyParm = RikParmToken EQUALS CommandKeySequence
ReturnKeyParm = RtkParmToken EQUALS CommandKeySequence
PosKeyParm = PskParmToken EQUALS KeyPadKey COMMA PosKeyAction
PosKeyAction = FirstSegmentToken / LastSegmentToken /
PreviousSegmentToken / NextSegmentToken /
CurrentSegmentToken
StopKeyParm = StkParmToken EQUALS KeyPadKey
StartInputKeyParm = SikParmToken EQUALS KeySet
EndInputKeyParm = EikParmToken EQUALS KeyPadKey
IncludeEndinputKey = IekParmToken EQUALS BOOLSTR
RecPersistParm = RpaParmToken EQUALS BOOLSTR
OverrideAudioParm = OaParmToken EQUALS SEGID
RestoreAudioParm = RaParmToken EQUALS SEGID
DeletePersistParm = DpaParmToken EQUALS SEGID
NumAttemptsParm = NaParmToken EQUALS NUMBER
VoiceInterruptParm = ViParmToken EQUALS BOOLSTR
IntKeySeqParm = IkParmToken EQUALS CommandKeySequence
AmtPlayedParm = ApParmToken EQUALS NUMBER
DigitsColParm = DcParmToken EQUALS KeySequence
RecordingIdParm = RiParmToken EQUALS NUMBER
ReturnCodeParm = RcParmToken EQUALS 3*3(DIGIT)
KeyPadKey = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
"*" / "#"
CommandKeySequence = 1*3(KeyPadKey)
KeySequence = 1*64(KeyPadKey)
KeySet = 1*11(KeyPadKey)
SignalParm = SgParmToken EQUALS ( PlayAnnToken / PlayColToken /
PlayRecToken ) RPAREN
Segmentlist = SegmentDescriptor *( COMMA SegmentDescriptor )
SegmentDescriptor = ( ( SegmentId [ EmbedVarList ]
[ SegSelectorList ] ) /
( TextToSpeechSeg [ SegSelectorList ] ) /
( DisplayTextSeg [ SegSelectorList ] ) /
( VariableSeg [ SegSelectorList ] ) /
SilenceSeg )
SegmentId = ( Segid / Alias )
TextToSpeechSeg = TextToSpeechSegToken LPAREN NAME RPAREN
DisplayTextSeg = DisplayTextSegToken LPAREN NAME RPAREN
SilenceSeg = SilenceSegToken LPAREN NAME RPAREN
VariableSeg = VariableSegToken LPAREN FullSpecVar RPAREN
Segid = NUMBER
Alias = SLASH NAME SLASH
EmbedVarList = LANGLE NAME *( COMMA NAME ) RANGLE
SegSelectorList = LSQUARE SegSelector *( COMMA SegSelector ) RSQUARE
SegSelector = NAME EQUALS NAME
FullSpecVar = ( DateVariable / DigitsVariable / DurationVariable /
MonthVariable / MoneyVariable / NumberVariable /
SilenceVariable / StringVariable / TextVariable /
TimeVariable / WeekdayVariable )
DateVariable = DateVarToken COMMA NullStrToken COMMA Date
Date = 8*8(DIGIT)
DigitsVariable = DigitsVarToken COMMA (NorthAmericanDnToken /
GenericDigitsToken) COMMA NUMBER
DurationVariable = DurationVarToken COMMA NullStrToken COMMA NUMBER
MoneyVariable = MoneyVarToken COMMA 3*3(ALPHA) COMMA OPTSIGNEDINT
MonthVariable = MonthVarToken COMMA NullStrToken COMMA Month
Month = "01" / "02" / "03" / "04" / "05" / "06" / "07" / "08" / "09" /
"10" / "11" / "12"
NumberVariable = (NumberVarToken COMMA CardinalNumberToken COMMA
OPTSIGNEDINT) / (NumberVarToken COMMA
OrdinalNumberToken COMMA NUMBER)
SilenceVariable = SilenceVarToken COMMA NullStrToken COMMA NUMBER
StringVariable = StringVarToken COMMA NullStrToken COMMA *(KeyPadKey)
OrdinalNumberToken) COMMA NUMBER
SilenceVariable = SilenceVarToken COMMA NullStrToken COMMA NUMBER
StringVariable = StringVarToken COMMA NullStrToken COMMA
*(KeyPadKey)
TextVariable = TextVarToken COMMA (DisplayTextToken /
TextToSpeechToken) COMMA NAME
TimeVariable = TimeVarToken COMMA (TwelveHourFormatToken /
TwentyFourHourFormatToken) COMMA 4*4(DIGIT)
WeekdayVariable = WeekdayVarToken COMMA NullStrToken COMMA NAME
AdvAudioPkgToken = "A"
PlayAnnToken = "pa"
PlayColToken = "pc"
PlayRecToken = "pr"
OpCompleteToken = "oc"
OpFailedToken = "of"
EndSignalToken = "es"
TextToSpeechSegToken = "ts"
DisplayTextSegToken = "dt"
SilenceSegToken = "si"
VariableSegToken = "vb"
AnParmToken = "an"
IpParmToken = "ip"
RpParmToken = "rp"
NdParmToken = "nd"
NsParmToken = "ns"
FaParmToken = "fa"
SaParmToken = "sa"
NiParmToken = "ni"
ItParmToken = "it"
IvParmToken = "iv"
DuParmToken = "du"
SpParmToken = "sp"
VlParmToken = "vl"
CbParmToken = "cb"
MxParmToken = "mx"
MnParmToken = "mn"
DpParmToken = "dp"
FdtParmToken = "fdt"
IdtParmToken = "idt"
EdtParmToken = "edt"
PrtParmToken = "prt"
PstParmToken = "pst"
RltParmToken = "rlt"
RskParmToken = "rsk"
RikParmToken = "rik"
RtkParmToken = "rtk"
PskParmToken = "psk"
StkParmToken = "stk"
SikParmToken = "sik"
EikParmToken = "eik"
IekParmToken = "iek"
RpaParmToken = "rpa"
DpaParmToken = "dpa"
OaParmToken = "oa"
RaParmToken = "ra"
NaParmToken = "na"
RidParmToken = "rid"
ViParmToken = "vi"
IkParmToken = "ik"
ApParmToken = "ap"
DcParmToken = "dc"
RiParmToken = "ri"
RcParmToken = "rc"
SgParmToken = "sg"
DateVarToken = "dat"
DigitsVarToken = "dig"
DuratioNVarToken = "dur"
MoneyVarToken = "mny"
MonthVarToken = "mth"
NumberVarToken = "num"
SilenceVarToken = "sil"
StringVarToken = "str"
TextVarToken = "txt"
TimeVarToken = "tme"
WeekdayVarToken = "wkd"
GenericDigitsToken = "gen"
NorthAmericanDnSToken = "ndn"
CardinalNumberToken = "crd"
OrdinalNumberToken = "ord"
DisplayTextToken = "dsp"
TextToSpeechToken = "spk"
TwelveHourFormatToken = "t12"
TwentyFourHourFormatToken = "t24"
NullStrToken = "null"
FirstSegmentToken = "fst"
LastSegmentToken = "lst"
PreviousSegmentToken = "prv"
NextSegmentToken = "nxt"
CurrentSegmentToken = "cur"
BOOLSTR = "true" / "false"
NAMECHAR = ALPHA / DIGIT / "_" / "-"
NAME = 1*64(NAMECHAR)
NUMBER = DIGIT *31(DIGIT)
SIGNEDINT = ("+" / "-") DIGIT *31(DIGIT)
OPTSIGNEDINT = ["+" / "-"] DIGIT *31(DIGIT)
EQUALS = "="
COMMA = ","
LSQUARE = "["
RSQUARE = "]"
LANGLE = "<"
RANGLE = ">"
LPAREN = "("
RPAREN = ")"
SLASH = "/"
WSP = SP / HTAB
13. References โจ
Here are the references, every single one, all the details included ๐
[1] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[2] Arango, M., Dugan, A., Elliott, I., Huitema, C. and S. Pickett, "Media Gateway Control Protocol (MGCP) Version 0.1", RFC 2705, October 1999.
[3] Cromwell, D. and M. Durling, "Requirements For Control Of A Media Services Function", Version 0.0, Work in Progres..
[4] ISO 639-2, "Code For The Representation Of Names Of Languages", 1998.
[5] ISO 4217, "Currency And Funds Code List", 1981.
[6] Cuervo, F., Hill, B., Greene, N., Huitema, C., Rayhan, A., Rosen, B. and J. Segers, "Megaco Protocol", RFC 2885, August 2000.
[7] ISO 8601, "International Date and Time Notation", 1998.
14. Author's Address ๐
David Cromwell
Nortel Networks
Box 13478
35 Davis Drive
Research Triangle Park, NC 27709
Phone: 919-991-8870
EMail: cromwell@nortelnetworks.com
15. Full Copyright Statement ๐
The legal bit is serious business, so I've kept every word exactly as written ๐ซถ
Copyright (C) The Internet Society (2000). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement ๐
Funding for the RFC Editor function is currently provided by the Internet Society. That's the whole RFC, bestie, we made it ๐ฆโจ๐
๐ฆ where this page comes from
- ietf: rfc2897 2000-08
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms