ActorRole
ControllerThink of it as the “brain” or IVR application logic. Decides what prompts to play, collects user input, branches dialogs, etc.
Media ServerThink of it as the “hands and ears” — actually plays audio, records voice, and collects DTMF tones.

The communication channel between them is the Media Control Channel Framework (MCCF), which is typically SIP-negotiated and reliable (e.g., TCP).

Key idea: The controller doesn’t handle audio directly; it sends instructions, and the media server executes them.

End-to-End Workflow

Let’s follow a call from start to finish.

Step 1: Session Setup

  1. A caller dials in.
  2. The SIP server routes the call to the IVR system.
  3. The IVR system’s controller opens a control channel to the media server using MCCF:
    • Negotiates capabilities.
    • Identifies which IVR package is supported (msc-ivr/1.0).

Conceptual view: The controller says:

“Hello media server, I want to control you using RFC 6231 IVR commands.”

Step 2: Prepare Dialog

Before playing prompts:

  1. Controller sends a <prepare> message.
  2. Includes:
    • Dialog ID (unique session identifier)
    • Resources: prompts (audio files), expected DTMF inputs
    • Optional configuration: timeout values, max retries

Media server response: ACK or error.

  • Confirms that resources are ready.
  • Ensures the controller doesn’t try to play a missing file.

Why this is important: It decouples preparation from execution — avoids race conditions or missing media.

Step 3: Start the Dialog

Controller sends <start> message with the dialog ID.

  • Media server begins IVR flow:
    1. Plays the first <prompt> (audio or TTS).
    2. Waits for user input if <collect> is specified.
    3. Can branch based on collected DTMF.

Example XML snippet:

<dialog id="123">
    <prompt src="welcome.wav"/>
    <collect maxdigits="1" timeout="5s"/>
</dialog>
  • Media server reads <prompt> → plays audio
  • Media server reads <collect> → waits for keypress

Controller’s job: Listen to events and decide what to do next.

Step 4: Event Reporting

Whenever something happens, the media server sends events back:

EventWhat it means
media-completeA prompt finished playing
dtmf-receivedUser pressed a key
record-completeRecording finished
errorSomething went wrong

Controller reacts:

  • If DTMF “1” → branch to sales menu
  • If no input → repeat prompt or hang up

Important: Events are asynchronous. The controller must maintain a state machine for each session.

Step 5: Dialog Control and Branching

Controller can send commands mid-dialog:

  • Pause: stop audio temporarily
  • Resume: continue playing
  • Stop: terminate dialog
  • Update: change prompts dynamically

This is the magic: The IVR can adapt in real time. For example: if a user is idle, the controller can insert a new prompt without restarting the session.

Step 6: Termination

Once the interaction finishes:

  1. Controller sends <terminate> with the dialog ID.
  2. Media server:
    • Stops any ongoing playback/recording
    • Frees resources
    • Sends final completion status
  3. Controller can then close the control channel or prepare for the next session.

Under the Hood: How Messages Are Structured

RFC 6231 uses XML over MCCF:

  • Request Message
<prepare-dialog dialog-id="abc123">
    <resource src="prompt1.wav"/>
</prepare-dialog>
  • Event/Response Message
<event dialog-id="abc123" name="dtmf-received">
    <digit>1</digit>
</event>
  • Messages carry:
    • Dialog ID (to tie events to a session)
    • Action type (prepare, start, collect, record)
    • Optional attributes (timeout, max digits, prompt source)
    • Payload (audio URL, DTMF info)

Visualize this:

Caller
  |
  v
Media Server <----> Controller
  |                   ^
  |-- Plays prompt      |-- Sends <start>/<prepare>/<terminate>
  |-- Captures DTMF     |-- Receives <event> notifications
  |-- Records voice

Everything is message-driven, like React’s state updates — the media server is “rendering” audio based on the XML instructions, and the controller “updates state” based on events.

The Concept: DTMF (Dual-Tone Multi-Frequency)

When you press a number on a phone keypad, it doesn’t just produce a single tone. It produces two simultaneous tones — one from a row, one from a column.

How a keypad maps to tones:

1209 Hz1336 Hz1477 Hz1633 Hz
697 Hz123A
770 Hz456B
852 Hz789C
941 Hz*0#D
  • Row frequency + column frequency = unique signature for each key.
  • This is called DTMF signaling.

So pressing “1” sends 697 Hz + 1209 Hz together as a short sound.

How Media Server Detects It

The media server is always “listening” to the audio channel. When a <collect> instruction is active:

  1. Audio from the caller is sent to the media server.
  2. The media server passes the audio through a DTMF decoder:

Steps of Decoding

  1. Band-pass filtering
    • Audio is split into frequency bands matching the DTMF rows and columns.
  2. Tone detection
    • Detect which two tones are present simultaneously.
    • Must ignore background noise, voice, etc.
  3. Mapping to digits
    • Each unique combination → a keypad number.
  4. Event generation
    • Once a valid tone is detected, the server generates a <dtmf-received> event back to the controller with the digit.

Example Event

<event dialog-id="123" name="dtmf-received">
    <digit>1</digit>
</event>
  • Controller receives this and knows the user pressed “1”.
  • Logic in the controller can then decide the next step (branching to sales, etc.).

What Makes It Reliable

  • Minimum tone duration: Media servers often require tones to be at least ~40–50 ms to count as valid.
  • Guard time: Ensures two keypresses aren’t merged.
  • Filtering voice/audio: DTMF decoders ignore human voice frequencies that might accidentally trigger a key.

Analogy: Like a Piano Detector

Think of DTMF like pressing two piano keys at once. The media server is like a program that listens to the chords and instantly says:

“Ah, that combination = note ‘1’!”