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