예제 #1
0
        unsafe public static void Detect(int _windowcount, float *window_segment, int stride, int sz, int bps, LpcWindowSection *sections)
        {
            int section_id = 0;
            var boundaries = new List <int>();
            var types      = new LpcWindowSection.SectionType[_windowcount, lpc.MAX_LPC_SECTIONS * 2];
            var alias      = new int[_windowcount, lpc.MAX_LPC_SECTIONS * 2];
            var alias_set  = new int[_windowcount, lpc.MAX_LPC_SECTIONS * 2];

            for (int x = 0; x < sz; x++)
            {
                for (int i = 0; i < _windowcount; i++)
                {
                    int   a  = alias[i, boundaries.Count];
                    float w  = window_segment[i * stride + x];
                    float wa = window_segment[a * stride + x];
                    if (wa != w)
                    {
                        for (int i1 = i; i1 < _windowcount; i1++)
                        {
                            if (alias[i1, boundaries.Count] == a &&
                                w == window_segment[i1 * stride + x])
                            {
                                alias[i1, boundaries.Count] = i;
                            }
                        }
                    }
                    if (boundaries.Count >= lpc.MAX_LPC_SECTIONS * 2)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    types[i, boundaries.Count] =
                        boundaries.Count >= lpc.MAX_LPC_SECTIONS * 2 - 2 ?
                        LpcWindowSection.SectionType.Data : w == 0.0 ?
                        LpcWindowSection.SectionType.Zero : w != 1.0 ?
                        LpcWindowSection.SectionType.Data : bps * 2 + BitReader.log2i(sz) >= 61 ?
                        LpcWindowSection.SectionType.OneLarge :
                        LpcWindowSection.SectionType.One;
                }
                bool isBoundary = false;
                for (int i = 0; i < _windowcount; i++)
                {
                    isBoundary |= boundaries.Count == 0 ||
                                  types[i, boundaries.Count - 1] != types[i, boundaries.Count];
                }
                if (isBoundary)
                {
                    for (int i = 0; i < _windowcount; i++)
                    {
                        for (int i1 = 0; i1 < _windowcount; i1++)
                        {
                            if (i != i1 && alias[i, boundaries.Count] == alias[i1, boundaries.Count])
                            {
                                alias_set[i, boundaries.Count] |= 1 << i1;
                            }
                        }
                    }
                    boundaries.Add(x);
                }
            }
            boundaries.Add(sz);
            var secs = new int[_windowcount];

            // Reconstruct segments list.
            for (int j = 0; j < boundaries.Count - 1; j++)
            {
                for (int i = 0; i < _windowcount; i++)
                {
                    LpcWindowSection *window_sections = sections + i * lpc.MAX_LPC_SECTIONS;
                    // leave room for glue
                    if (secs[i] >= lpc.MAX_LPC_SECTIONS - 1)
                    {
                        throw new IndexOutOfRangeException();
                        window_sections[secs[i] - 1].m_type = LpcWindowSection.SectionType.Data;
                        window_sections[secs[i] - 1].m_end  = boundaries[j + 1];
                        continue;
                    }
                    window_sections[secs[i]].setData(boundaries[j], boundaries[j + 1]);
                    window_sections[secs[i]++].m_type = types[i, j];
                }
                for (int i = 0; i < _windowcount; i++)
                {
                    LpcWindowSection *window_sections = sections + i * lpc.MAX_LPC_SECTIONS;
                    int sec = secs[i] - 1;
                    if (sec > 0 &&
                        j > 0 && (alias_set[i, j] == alias_set[i, j - 1] || window_sections[sec].m_type == SectionType.Zero) &&
                        window_sections[sec].m_start == boundaries[j] &&
                        window_sections[sec].m_end == boundaries[j + 1] &&
                        window_sections[sec - 1].m_end == boundaries[j] &&
                        window_sections[sec - 1].m_type == window_sections[sec].m_type)
                    {
                        window_sections[sec - 1].m_end = window_sections[sec].m_end;
                        secs[i]--;
                        continue;
                    }
                    if (section_id >= lpc.MAX_LPC_SECTIONS)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    if (alias_set[i, j] != 0 &&
                        types[i, j] != SectionType.Zero &&
                        section_id < lpc.MAX_LPC_SECTIONS)
                    {
                        for (int i1 = i; i1 < _windowcount; i1++)
                        {
                            if (alias[i1, j] == i && secs[i1] > 0)
                            {
                                sections[i1 * lpc.MAX_LPC_SECTIONS + secs[i1] - 1].m_id = section_id;
                            }
                        }
                        section_id++;
                    }
                    // TODO: section_id for glue? nontrivial, must be sure next sections are the same size
                    if (sec > 0 &&
                        (window_sections[sec].m_type == SectionType.One || window_sections[sec].m_type == SectionType.OneLarge) &&
                        window_sections[sec].m_end - window_sections[sec].m_start >= lpc.MAX_LPC_ORDER &&
                        (window_sections[sec - 1].m_type == SectionType.One || window_sections[sec - 1].m_type == SectionType.OneLarge) &&
                        window_sections[sec - 1].m_end - window_sections[sec - 1].m_start >= lpc.MAX_LPC_ORDER)
                    {
                        window_sections[sec + 1]    = window_sections[sec];
                        window_sections[sec].m_end  = window_sections[sec].m_start;
                        window_sections[sec].m_type = SectionType.OneGlue;
                        window_sections[sec].m_id   = -1;
                        secs[i]++;
                        continue;
                    }
                    if (sec > 0 &&
                        window_sections[sec].m_type != SectionType.Zero &&
                        window_sections[sec - 1].m_type != SectionType.Zero)
                    {
                        window_sections[sec + 1]    = window_sections[sec];
                        window_sections[sec].m_end  = window_sections[sec].m_start;
                        window_sections[sec].m_type = SectionType.Glue;
                        window_sections[sec].m_id   = -1;
                        secs[i]++;
                        continue;
                    }
                }
            }
            for (int i = 0; i < _windowcount; i++)
            {
                for (int s = 0; s < secs[i]; s++)
                {
                    LpcWindowSection *window_sections = sections + i * lpc.MAX_LPC_SECTIONS;
                    if (window_sections[s].m_type == SectionType.Glue ||
                        window_sections[s].m_type == SectionType.OneGlue)
                    {
                        window_sections[s].m_end = window_sections[s + 1].m_end;
                    }
                }
                while (secs[i] < lpc.MAX_LPC_SECTIONS)
                {
                    LpcWindowSection *window_sections = sections + i * lpc.MAX_LPC_SECTIONS;
                    window_sections[secs[i]++].setZero(sz, sz);
                }
            }
        }