OSDN Git Service

#39474 Riff chunked oggを使った曲を再生しようとすると、DTXManiaが強制終了する問題を修正。
[dtxmania/dtxmania.git] / NVorbis / VorbisMode.cs
1 /****************************************************************************
2  * NVorbis                                                                  *
3  * Copyright (C) 2014, Andrew Ward <afward@gmail.com>                       *
4  *                                                                          *
5  * See COPYING for license terms (Ms-PL).                                   *
6  *                                                                          *
7  ***************************************************************************/
8 using System;
9 using System.IO;
10
11 namespace NVorbis
12 {
13     class VorbisMode
14     {
15         const float M_PI = 3.1415926539f; //(float)Math.PI;
16         const float M_PI2 = M_PI / 2;
17
18         internal static VorbisMode Init(VorbisStreamDecoder vorbis, DataPacket packet)
19         {
20             var mode = new VorbisMode(vorbis);
21             mode.BlockFlag = packet.ReadBit();
22             mode.WindowType = (int)packet.ReadBits(16);
23             mode.TransformType = (int)packet.ReadBits(16);
24             var mapping = (int)packet.ReadBits(8);
25
26             if (mode.WindowType != 0 || mode.TransformType != 0 || mapping >= vorbis.Maps.Length) throw new InvalidDataException();
27
28             mode.Mapping = vorbis.Maps[mapping];
29             mode.BlockSize = mode.BlockFlag ? vorbis.Block1Size : vorbis.Block0Size;
30
31             // now pre-calc the window(s)...
32             if (mode.BlockFlag)
33             {
34                 // long block
35                 mode._windows = new float[4][];
36                 mode._windows[0] = new float[vorbis.Block1Size];
37                 mode._windows[1] = new float[vorbis.Block1Size];
38                 mode._windows[2] = new float[vorbis.Block1Size];
39                 mode._windows[3] = new float[vorbis.Block1Size];
40             }
41             else
42             {
43                 // short block
44                 mode._windows = new float[1][];
45                 mode._windows[0] = new float[vorbis.Block0Size];
46             }
47             mode.CalcWindows();
48
49             return mode;
50         }
51
52         VorbisStreamDecoder _vorbis;
53
54         float[][] _windows;
55
56         private VorbisMode(VorbisStreamDecoder vorbis)
57         {
58             _vorbis = vorbis;
59         }
60
61         void CalcWindows()
62         {
63             // 0: prev = s, next = s || BlockFlag = false
64             // 1: prev = l, next = s
65             // 2: prev = s, next = l
66             // 3: prev = l, next = l
67
68             for (int idx = 0; idx < _windows.Length; idx++)
69             {
70                 var array = _windows[idx];
71
72                 var left = ((idx & 1) == 0 ? _vorbis.Block0Size : _vorbis.Block1Size) / 2;
73                 var wnd = BlockSize;
74                 var right = ((idx & 2) == 0 ? _vorbis.Block0Size : _vorbis.Block1Size) / 2;
75
76                 var leftbegin = wnd / 4 - left / 2;
77                 var rightbegin = wnd - wnd / 4 - right / 2;
78
79                 for (int i = 0; i < left; i++)
80                 {
81                     var x = (float)Math.Sin((i + .5) / left * M_PI2);
82                     x *= x;
83                     array[leftbegin + i] = (float)Math.Sin(x * M_PI2);
84                 }
85
86                 for (int i = leftbegin + left; i < rightbegin; i++)
87                 {
88                     array[i] = 1.0f;
89                 }
90
91                 for (int i = 0; i < right; i++)
92                 {
93                     var x = (float)Math.Sin((right - i - .5) / right * M_PI2);
94                     x *= x;
95                     array[rightbegin + i] = (float)Math.Sin(x * M_PI2);
96                 }
97             }
98         }
99
100         internal bool BlockFlag;
101         internal int WindowType;
102         internal int TransformType;
103         internal VorbisMapping Mapping;
104         internal int BlockSize;
105
106         internal float[] GetWindow(bool prev, bool next)
107         {
108             if (BlockFlag)
109             {
110                 if (next)
111                 {
112                     if (prev) return _windows[3];
113                     return _windows[2];
114                 }
115                 else if (prev)
116                 {
117                     return _windows[1];
118                 }
119             }
120
121             return _windows[0];
122         }
123     }
124 }