<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* The tables in this file are fixed by RFC 6716, the specification for
* the Opus audio codec. They are taken from the reference
* implementation published by Xiph.Org, Skype Limited and others, which
* is offered under a three clause licence allowing use in other
* software so long as its notice is carried along:
*
* Copyright 2001-2023 Xiph.Org, Skype Limited, Octasic, Jean-Marc
* Valin, Timothy B. Terriberry, CSIRO, Gregory Maxwell, Mark
* Borgerding, Erik de Castro Lopo, Mozilla, Amazon.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the copyright notice,
* this list of conditions and the disclaimer are retained. This
* software is provided by the copyright holders as is, and any
* warranty is disclaimed.
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\library\av_processing;
/**
* SpeechPitchTables holds the tables that say at what pitch a stretch of
* speech was spoken and how strongly that pitch repeats.
*
* Speech made with the voice repeats itself: the vocal folds open and
* close at some rate, and one opening sounds much like the one before
* it. A stretch therefore carries how far back its own recent past to
* look, called the lag, and a short filter saying how much of what was
* found there to add back in. This file holds the likelihoods for
* reading the lag and the filter, and the books of filters themselves.
*
* @author Chris Pollett
*/
class SpeechPitchTables
{
/**
* WHOLE_BITS is how many bits the likelihoods in this file add up
* to, as in the rest of the speech decoding.
*/
const WHOLE_BITS = 8;
/**
* QUARTERS_IN_STRETCH is how many quarters a stretch is cut into.
* Each quarter carries its own lag, worked out from the stretch's
* own lag and a shape shared across the four.
*/
const QUARTERS_IN_STRETCH = 4;
/**
* LEAST_LAG_WIDE and MOST_LAG_WIDE are how far back a stretch of
* wide sound may look, in samples at sixteen thousand a second.
* Two milliseconds is the shortest a voice repeats in and eighteen
* the longest.
*/
const LEAST_LAG_WIDE = 32;
/**
* MOST_LAG_WIDE is the furthest back a stretch of wide sound may
* look, in samples at sixteen thousand a second.
*/
const MOST_LAG_WIDE = 288;
/**
* LAG_STEPS_WIDE is how many places within one coarse step of lag a
* stretch of wide sound may name, which fixes how finely the pitch
* can be written.
*/
const LAG_STEPS_WIDE = 8;
/**
* REPEAT_LEAN_SCALES is how much of the sound before a stretch is
* leaned on when the stretch stands on its own, one for each of the
* three answers it may write. Leaning less on a lost stretch keeps a
* lost packet from spoiling the one after it.
*/
const REPEAT_LEAN_SCALES = [15565, 12288, 8192];
/**
* SOUND_KEPT_MILLISECONDS is how much of the sound before a stretch
* is kept, so a stretch reaching back for its pitch has something to
* reach into.
*/
const SOUND_KEPT_MILLISECONDS = 20;
/**
* PITCH_FINE_LAG is how likely each place within one coarse step of
* lag was. The eight places are equally likely, so the table counts
* down evenly.
*/
const PITCH_FINE_LAG = [224, 192, 160, 128, 96, 64, 32, 0];
/**
* PITCH_FIRST_LAG is how likely each coarse step of lag was where a
* stretch writes its pitch outright rather than as a change from
* the stretch before it.
*/
const PITCH_FIRST_LAG = [
253, 250, 244, 233, 212, 182, 150, 131, 120, 110, 98, 85, 72,
60, 49, 40, 32, 25, 19, 15, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
/**
* PITCH_LAG_CHANGE is how likely each change of lag was where a
* stretch writes its pitch as a move from the stretch before. Pitch
* moves slowly in speech, so a small change is far likelier than a
* large one.
*/
const PITCH_LAG_CHANGE = [
210, 208, 206, 203, 199, 193, 183, 168, 142, 104, 74, 52, 37,
27, 20, 14, 10, 6, 4, 2, 0];
/**
* PITCH_SHAPE_WIDE is how likely each shape of pitch across the
* four quarters was, for wide sound at twenty milliseconds a
* stretch. A shape says how the lag drifts within the stretch.
*/
const PITCH_SHAPE_WIDE = [
223, 201, 183, 167, 152, 138, 124, 111, 98, 88, 79, 70, 62, 56,
50, 44, 39, 35, 31, 27, 24, 21, 18, 16, 14, 12, 10, 8, 6, 4, 3,
2, 1, 0];
/**
* PITCH_SHAPE_WIDE_STEPS is the shapes themselves, four numbers to
* a shape, each the step to add to the stretch's own lag for that
* quarter.
*/
const PITCH_SHAPE_WIDE_STEPS = [
0, 0, 1, -1, 0, 1, -1, 0, -1, 1, -2, 2, -2, -2, 2, -3, 2, 3, -3,
-4, 3, -4, 4, 4, -5, 5, -6, -5, 6, -7, 6, 5, 8, -9, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 1, -1, 0, 1, -1, -1, 1, -1, 2, 1,
-1, 2, -2, -2, 2, -2, 2, 2, 3, -3, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 1, -1, 1, 0, 0, 2, 1, -1, 2, -1, -1, 2, -1, 2, 2, -1,
3, -2, -2, -2, 3, 0, 1, 0, 0, 1, 0, 1, -1, 2, -1, 2, -1, 2, 3,
-2, 3, -2, -2, 4, 4, -3, 5, -3, -4, 6, -4, 6, 5, -5, 8, -6, -5,
-7, 9];
/**
* REPEAT_STRENGTH_CHANCES_0 is how likely each filter of the
* smallest book was. A stretch whose pitch repeats weakly uses this
* book, which holds eight filters.
*/
const REPEAT_STRENGTH_CHANCES_0 = [
71, 56, 43, 30, 21, 12, 6, 0];
/**
* REPEAT_STRENGTH_CHANCES_1 is how likely each filter of the middle
* book was, which holds sixteen filters.
*/
const REPEAT_STRENGTH_CHANCES_1 = [
199, 165, 144, 124, 109, 96, 84, 71, 61, 51, 42, 32, 23, 15, 8,
0];
/**
* REPEAT_STRENGTH_CHANCES_2 is how likely each filter of the
* largest book was, which holds thirty-two filters.
*/
const REPEAT_STRENGTH_CHANCES_2 = [
241, 225, 211, 199, 187, 175, 164, 153, 142, 132, 123, 114, 105,
96, 88, 80, 72, 64, 57, 50, 44, 38, 33, 29, 24, 20, 16, 12, 9,
5, 2, 0];
/**
* REPEAT_BOOK_CHANCES is how likely each of the three books of
* filters was. A stretch names one book and then one filter within
* it, for all four quarters together.
*/
const REPEAT_BOOK_CHANCES = [
179, 99, 0];
/**
* REPEAT_FILTERS_0 is the smallest book of filters, five taps to a
* filter. A tap says how much of the sound one sample either side
* of the lag to add back in.
*/
const REPEAT_FILTERS_0 = [
4, 6, 24, 7, 5, 0, 0, 2, 0, 0, 12, 28, 41, 13, -4, -9, 15, 42,
25, 14, 1, -2, 62, 41, -9, -10, 37, 65, -4, 3, -6, 4, 66, 7, -8,
16, 14, 38, -3, 33];
/**
* REPEAT_FILTERS_1 is the middle book of filters, five taps to a
* filter.
*/
const REPEAT_FILTERS_1 = [
13, 22, 39, 23, 12, -1, 36, 64, 27, -6, -7, 10, 55, 43, 17, 1,
1, 8, 1, 1, 6, -11, 74, 53, -9, -12, 55, 76, -12, 8, -3, 3, 93,
27, -4, 26, 39, 59, 3, -8, 2, 0, 77, 11, 9, -8, 22, 44, -6, 7,
40, 9, 26, 3, 9, -7, 20, 101, -7, 4, 3, -8, 42, 26, 0, -15, 33,
68, 2, 23, -2, 55, 46, -2, 15, 3, -1, 21, 16, 41];
/**
* REPEAT_FILTERS_2 is the largest book of filters, five taps to a
* filter.
*/
const REPEAT_FILTERS_2 = [
-6, 27, 61, 39, 5, -11, 42, 88, 4, 1, -2, 60, 65, 6, -4, -1, -5,
73, 56, 1, -9, 19, 94, 29, -9, 0, 12, 99, 6, 4, 8, -19, 102, 46,
-13, 3, 2, 13, 3, 2, 9, -21, 84, 72, -18, -11, 46, 104, -22, 8,
18, 38, 48, 23, 0, -16, 70, 83, -21, 11, 5, -11, 117, 22, -8,
-6, 23, 117, -12, 3, 3, -8, 95, 28, 4, -10, 15, 77, 60, -15, -1,
4, 124, 2, -4, 3, 38, 84, 24, -25, 2, 13, 42, 13, 31, 21, -4,
56, 46, -1, -1, 35, 79, -13, 19, -7, 65, 88, -9, -14, 20, 4, 81,
49, -29, 20, 0, 75, 3, -17, 5, -9, 44, 92, -8, 1, -3, 22, 69,
31, -6, 95, 41, -12, 5, 39, 67, 16, -4, 1, 0, -6, 120, 55, -36,
-13, 44, 122, 4, -24, 81, 5, 11, 3, 7, 2, 0, 9, 10, 88];
}