OSDN Git Service

#38036 どこでCTextureの解放漏れが発生しているかを容易に識別できるようにするために、CTextureの生成時にラベルを付与できるようにした。(引数最後にラベ...
[dtxmania/dtxmania.git] / NVorbis / RingBuffer.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.Collections.Generic;
10 using System.Linq;
11 using System.Text;
12
13 namespace NVorbis
14 {
15     class RingBuffer
16     {
17         float[] _buffer;
18         int _start;
19         int _end;
20         int _bufLen;
21
22         internal RingBuffer(int size)
23         {
24             _buffer = new float[size];
25             _start = _end = 0;
26             _bufLen = size;
27         }
28
29         internal void EnsureSize(int size)
30         {
31             // because _end == _start signifies no data, and _end is always 1 more than the data we have, we must make the buffer {channels} entries bigger than requested
32             size += Channels;
33
34             if (_bufLen < size)
35             {
36                 var temp = new float[size];
37                 Array.Copy(_buffer, _start, temp, 0, _bufLen - _start);
38                 if (_end < _start)
39                 {
40                     Array.Copy(_buffer, 0, temp, _bufLen - _start, _end);
41                 }
42                 var end = Length;
43                 _start = 0;
44                 _end = end;
45                 _buffer = temp;
46
47                 _bufLen = size;
48             }
49         }
50
51         internal int Channels;
52
53         internal void CopyTo(float[] buffer, int index, int count)
54         {
55             if (index < 0 || index + count > buffer.Length) throw new ArgumentOutOfRangeException("index");
56
57             var start = _start;
58             RemoveItems(count);
59
60             // this is used to pull data out of the buffer, so we'll update the start position too...
61             var len = (_end - start + _bufLen) % _bufLen;
62             if (count > len) throw new ArgumentOutOfRangeException("count");
63
64             var cnt = Math.Min(count, _bufLen - start);
65             Buffer.BlockCopy(_buffer, start * sizeof(float), buffer, index * sizeof(float), cnt * sizeof(float));
66
67             if (cnt < count)
68             {
69                 Buffer.BlockCopy(_buffer, 0, buffer, (index + cnt) * sizeof(float), (count - cnt) * sizeof(float));
70             }
71         }
72
73         internal void RemoveItems(int count)
74         {
75             var cnt = (count + _start) % _bufLen;
76             if (_end > _start)
77             {
78                 if (cnt > _end || cnt < _start) throw new ArgumentOutOfRangeException();
79             }
80             else
81             {
82                 // wrap-around
83                 if (cnt < _start && cnt > _end) throw new ArgumentOutOfRangeException();
84             }
85
86             _start = cnt;
87         }
88
89         internal void Clear()
90         {
91             _start = _end = 0;
92         }
93
94         internal int Length
95         {
96             get
97             {
98                 var temp = _end - _start;
99                 if (temp < 0) temp += _bufLen;
100                 return temp;
101             }
102         }
103
104         internal void Write(int channel, int index, int start, int switchPoint, int end, float[] pcm, float[] window)
105         {
106             // this is the index of the first sample to merge
107             var idx = (index + start) * Channels + channel + _start;
108             while (idx >= _bufLen)
109             {
110                 idx -= _bufLen;
111             }
112
113             // blech...  gotta fix the first packet's pointers
114             if (idx < 0)
115             {
116                 start -= index;
117                 idx = channel;
118             }
119
120             // go through and do the overlap
121             for (; idx < _bufLen && start < switchPoint; idx += Channels, ++start)
122             {
123                 _buffer[idx] += pcm[start] * window[start];
124             }
125             if (idx >= _bufLen)
126             {
127                 idx -= _bufLen;
128                 for (; start < switchPoint; idx += Channels, ++start)
129                 {
130                     _buffer[idx] += pcm[start] * window[start];
131                 }
132             }
133
134             // go through and write the rest
135             for (; idx < _bufLen && start < end; idx += Channels, ++start)
136             {
137                 _buffer[idx] = pcm[start] * window[start];
138             }
139             if (idx >= _bufLen)
140             {
141                 idx -= _bufLen;
142                 for (; start < end; idx += Channels, ++start)
143                 {
144                     _buffer[idx] = pcm[start] * window[start];
145                 }
146             }
147
148             // finally, make sure the buffer end is set correctly
149             _end = idx;
150         }
151     }
152 }