Home | History | Annotate | Download | only in neteq
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/audio_coding/neteq/dtmf_buffer.h"
     12 
     13 #include <assert.h>
     14 #include <algorithm>  // max
     15 
     16 // Modify the code to obtain backwards bit-exactness. Once bit-exactness is no
     17 // longer required, this #define should be removed (and the code that it
     18 // enables).
     19 #define LEGACY_BITEXACT
     20 
     21 namespace webrtc {
     22 
     23 // The ParseEvent method parses 4 bytes from |payload| according to this format
     24 // from RFC 4733:
     25 //
     26 //  0                   1                   2                   3
     27 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     29 // |     event     |E|R| volume    |          duration             |
     30 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     31 //
     32 // Legend (adapted from RFC 4733)
     33 // - event:    The event field is a number between 0 and 255 identifying a
     34 //             specific telephony event. The buffer will not accept any event
     35 //             numbers larger than 15.
     36 // - E:        If set to a value of one, the "end" bit indicates that this
     37 //             packet contains the end of the event.  For long-lasting events
     38 //             that have to be split into segments, only the final packet for
     39 //             the final segment will have the E bit set.
     40 // - R:        Reserved.
     41 // - volume:   For DTMF digits and other events representable as tones, this
     42 //             field describes the power level of the tone, expressed in dBm0
     43 //             after dropping the sign.  Power levels range from 0 to -63 dBm0.
     44 //             Thus, larger values denote lower volume. The buffer discards
     45 //             values larger than 36 (i.e., lower than -36 dBm0).
     46 // - duration: The duration field indicates the duration of the event or segment
     47 //             being reported, in timestamp units, expressed as an unsigned
     48 //             integer in network byte order.  For a non-zero value, the event
     49 //             or segment began at the instant identified by the RTP timestamp
     50 //             and has so far lasted as long as indicated by this parameter.
     51 //             The event may or may not have ended.  If the event duration
     52 //             exceeds the maximum representable by the duration field, the
     53 //             event is split into several contiguous segments. The buffer will
     54 //             discard zero-duration events.
     55 //
     56 int DtmfBuffer::ParseEvent(uint32_t rtp_timestamp,
     57                            const uint8_t* payload,
     58                            int payload_length_bytes,
     59                            DtmfEvent* event) {
     60   if (!payload || !event) {
     61     return kInvalidPointer;
     62   }
     63   if (payload_length_bytes < 4) {
     64     return kPayloadTooShort;
     65   }
     66 
     67   event->event_no = payload[0];
     68   event->end_bit = ((payload[1] & 0x80) != 0);
     69   event->volume = (payload[1] & 0x3F);
     70   event->duration = payload[2] << 8 | payload[3];
     71   event->timestamp = rtp_timestamp;
     72   return kOK;
     73 }
     74 
     75 // Inserts a DTMF event into the buffer. The event should be parsed from the
     76 // bit stream using the ParseEvent method above before inserting it in the
     77 // buffer.
     78 // DTMF events can be quite long, and in most cases the duration of the event
     79 // is not known when the first packet describing it is sent. To deal with that,
     80 // the RFC 4733 specifies that multiple packets are sent for one and the same
     81 // event as it is being created (typically, as the user is pressing the key).
     82 // These packets will all share the same start timestamp and event number,
     83 // while the duration will be the cumulative duration from the start. When
     84 // inserting a new event, the InsertEvent method tries to find a matching event
     85 // already in the buffer. If so, the new event is simply merged with the
     86 // existing one.
     87 int DtmfBuffer::InsertEvent(const DtmfEvent& event) {
     88   if (event.event_no < 0 || event.event_no > 15 ||
     89       event.volume < 0 || event.volume > 36 ||
     90       event.duration <= 0 || event.duration > 65535) {
     91     return kInvalidEventParameters;
     92   }
     93   DtmfList::iterator it = buffer_.begin();
     94   while (it != buffer_.end()) {
     95     if (MergeEvents(it, event)) {
     96       // A matching event was found and the new event was merged.
     97       return kOK;
     98     }
     99     ++it;
    100   }
    101   buffer_.push_back(event);
    102   // Sort the buffer using CompareEvents to rank the events.
    103   buffer_.sort(CompareEvents);
    104   return kOK;
    105 }
    106 
    107 bool DtmfBuffer::GetEvent(uint32_t current_timestamp, DtmfEvent* event) {
    108   DtmfList::iterator it = buffer_.begin();
    109   while (it != buffer_.end()) {
    110     // |event_end| is an estimate of where the current event ends. If the end
    111     // bit is set, we know that the event ends at |timestamp| + |duration|.
    112     uint32_t event_end = it->timestamp + it->duration;
    113 #ifdef LEGACY_BITEXACT
    114     bool next_available = false;
    115 #endif
    116     if (!it->end_bit) {
    117       // If the end bit is not set, we allow extrapolation of the event for
    118       // some time.
    119       event_end += max_extrapolation_samples_;
    120       DtmfList::iterator next = it;
    121       ++next;
    122       if (next != buffer_.end()) {
    123         // If there is a next event in the buffer, we will not extrapolate over
    124         // the start of that new event.
    125         event_end = std::min(event_end, next->timestamp);
    126 #ifdef LEGACY_BITEXACT
    127         next_available = true;
    128 #endif
    129       }
    130     }
    131     if (current_timestamp >= it->timestamp
    132         && current_timestamp <= event_end) {  // TODO(hlundin): Change to <.
    133       // Found a matching event.
    134       if (event) {
    135         event->event_no = it->event_no;
    136         event->end_bit = it->end_bit;
    137         event->volume = it->volume;
    138         event->duration = it->duration;
    139         event->timestamp = it->timestamp;
    140       }
    141 #ifdef LEGACY_BITEXACT
    142       if (it->end_bit &&
    143           current_timestamp + frame_len_samples_ >= event_end) {
    144         // We are done playing this. Erase the event.
    145         buffer_.erase(it);
    146       }
    147 #endif
    148       return true;
    149     } else if (current_timestamp > event_end) {  // TODO(hlundin): Change to >=.
    150       // Erase old event. Operation returns a valid pointer to the next element
    151       // in the list.
    152 #ifdef LEGACY_BITEXACT
    153       if (!next_available) {
    154         if (event) {
    155           event->event_no = it->event_no;
    156           event->end_bit = it->end_bit;
    157           event->volume = it->volume;
    158           event->duration = it->duration;
    159           event->timestamp = it->timestamp;
    160         }
    161         it = buffer_.erase(it);
    162         return true;
    163       } else {
    164         it = buffer_.erase(it);
    165       }
    166 #else
    167       it = buffer_.erase(it);
    168 #endif
    169     } else {
    170       ++it;
    171     }
    172   }
    173   return false;
    174 }
    175 
    176 int DtmfBuffer::SetSampleRate(int fs_hz) {
    177   if (fs_hz != 8000 &&
    178       fs_hz != 16000 &&
    179       fs_hz != 32000 &&
    180       fs_hz != 48000) {
    181     return kInvalidSampleRate;
    182   }
    183   max_extrapolation_samples_ = 7 * fs_hz / 100;
    184   frame_len_samples_ = fs_hz / 100;
    185   return kOK;
    186 }
    187 
    188 // The method returns true if the two events are considered to be the same.
    189 // The are defined as equal if they share the same timestamp and event number.
    190 // The special case with long-lasting events that have to be split into segments
    191 // is not handled in this method. These will be treated as separate events in
    192 // the buffer.
    193 bool DtmfBuffer::SameEvent(const DtmfEvent& a, const DtmfEvent& b) {
    194   return (a.event_no == b.event_no) && (a.timestamp == b.timestamp);
    195 }
    196 
    197 bool DtmfBuffer::MergeEvents(DtmfList::iterator it, const DtmfEvent& event) {
    198   if (SameEvent(*it, event)) {
    199     if (!it->end_bit) {
    200       // Do not extend the duration of an event for which the end bit was
    201       // already received.
    202       it->duration = std::max(event.duration, it->duration);
    203     }
    204     if (event.end_bit) {
    205       it->end_bit = true;
    206     }
    207     return true;
    208   } else {
    209     return false;
    210   }
    211 }
    212 
    213 // Returns true if |a| goes before |b| in the sorting order ("|a| < |b|").
    214 // The events are ranked using their start timestamp (taking wrap-around into
    215 // account). In the unlikely situation that two events share the same start
    216 // timestamp, the event number is used to rank the two. Note that packets
    217 // that belong to the same events, and therefore sharing the same start
    218 // timestamp, have already been merged before the sort method is called.
    219 bool DtmfBuffer::CompareEvents(const DtmfEvent& a, const DtmfEvent& b) {
    220   if (a.timestamp == b.timestamp) {
    221     return a.event_no < b.event_no;
    222   }
    223   // Take wrap-around into account.
    224   return (static_cast<uint32_t>(b.timestamp - a.timestamp) < 0xFFFFFFFF / 2);
    225 }
    226 }  // namespace webrtc
    227