1 /************************************************************************
3 * Copyright 2012 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ************************************************************************/
24 SoundFileStream::SoundFileStream() : _data(0), _dataSize(0), _dataOffset(0)
27 SoundFileStream::SoundFileStream( SNDFILE
*sf
, const SF_INFO
&info
, sf_count_t b
, sf_count_t d
)
30 load( sf
, info
, b
, d
);
33 SoundFileStream::~SoundFileStream()
38 void SoundFileStream::load( SNDFILE
*sf
, const SF_INFO
&info
, sf_count_t beg
, sf_count_t dur
)
45 _data
= new short [_dataSize
* info
.channels
];
46 sf_seek( sf
, _dataOffset
, SEEK_SET
);
47 _dataSize
= sf_readf_short( sf
, _data
, _dataSize
);
54 bool SoundFileStream::integrate
55 ( int ch
, double f_beg
, double f_dur
,
56 short *minBuffer
, short *maxBuffer
, float *sumBuf
, float *sum2Buf
, int bufferSize
)
60 && ( f_beg
>= beginning() )
61 && ( f_beg
+ f_dur
<= beginning() + duration() );
62 if( !ok
) return false;
64 double fpu
= f_dur
/ bufferSize
;
65 double f_pos
= f_beg
- _dataOffset
;
66 double f_pos_max
= _dataSize
;
69 for( i
= 0; i
< bufferSize
; ++i
) {
70 int data_pos
= floor(f_pos
);
74 // slower, but error-proof:
75 // f_pos = (double)(i+1) / width() * f_dur + f_beg;
77 // the following is a faster variant, but floating point operations are fallible,
78 // so we need to make sure we stay within the constraints of f_dur;
79 double f_pos1
= f_pos
+ fpu
;
80 if( f_pos1
> f_pos_max
) f_pos1
= f_pos_max
;
82 int frame_count
= ceil(f_pos1
) - data_pos
;
84 float frac0
= data_pos
+ 1.f
- f_pos
;
85 float frac1
= f_pos1
+ 1.f
- ceil(f_pos1
);
87 // get min, max and sum
88 short *samples
= _data
+ (data_pos
* channels()) + ch
;
94 for( f
= 0; f
< frame_count
; ++f
, samples
+= channels() ){
95 // TODO should we overlap min-max or not here?
96 float sample
= *samples
;
98 if( f
== 0 ) frac
= frac0
;
99 else if( f
== frame_count
- 1 ) frac
= frac1
;
102 if( sample
< min
) min
= sample
;
103 if( sample
> max
) max
= sample
;
105 sum
+= sample
* frac
;
106 sum2
+= sample
* sample
* frac
;
120 bool SoundFileStream::displayData
121 ( int ch
, double f_beg
, double f_dur
,
122 short *minBuffer
, short *maxBuffer
, short *minRMS
, short *maxRMS
, int bufferSize
)
126 && ( f_beg
>= beginning() )
127 && ( f_beg
+ f_dur
<= beginning() + duration() );
128 if( !ok
) return false;
130 double fpu
= f_dur
/ bufferSize
;
131 double f_pos
= f_beg
- _dataOffset
;
132 double f_pos_max
= _dataSize
;
134 short min
= SHRT_MAX
;
135 short max
= SHRT_MIN
;
137 double D_SHRT_MAX
= (double) SHRT_MAX
;
138 double D_SHRT_MIN
= (double) SHRT_MIN
;
141 for( i
= 0; i
< bufferSize
; ++i
) {
142 int data_pos
= floor(f_pos
);
144 // increment position
146 // slower, but error-proof:
147 // f_pos = (double)(i+1) / width() * f_dur + f_beg;
149 // the following is a faster variant, but floating point operations are fallible,
150 // so we need to make sure we stay within the constraints of f_dur;
151 double f_pos1
= f_pos
+ fpu
;
152 if( f_pos1
> f_pos_max
) f_pos1
= f_pos_max
;
154 int frame_count
= ceil(f_pos1
) - data_pos
;
156 float frac0
= data_pos
+ 1.f
- f_pos
;
157 float frac1
= f_pos1
+ 1.f
- ceil(f_pos1
);
159 // get min, max and sum
160 short *samples
= _data
+ (data_pos
* channels()) + ch
;
165 for( f
= 0; f
< frame_count
; ++f
, samples
+= channels() ){
166 // TODO should we overlap min-max or not here?
167 float sample
= *samples
;
169 if( f
== 0 ) frac
= frac0
;
170 else if( f
== frame_count
- 1 ) frac
= frac1
;
173 if( sample
< min
) min
= sample
;
174 if( sample
> max
) max
= sample
;
176 sum
+= sample
* frac
;
177 sum2
+= sample
* sample
* frac
;
181 double avg
= sum
/ n
;
182 double stdDev
= sqrt( abs((sum2
- (sum
*avg
) ) / n
) );
186 minRMS
[i
] = std::max(D_SHRT_MIN
, std::min(D_SHRT_MAX
, avg
- stdDev
));
187 maxRMS
[i
] = std::max(D_SHRT_MIN
, std::min(D_SHRT_MAX
, avg
+ stdDev
));
197 short *SoundFileStream::rawFrames( int ch
, sf_count_t b
, sf_count_t d
, bool *interleaved
)
199 if( ch
> channels() || b
< _dataOffset
|| b
+ d
> _dataOffset
+ _dataSize
) return 0;
201 sf_count_t offset
= (b
- _dataOffset
) * channels() + ch
;
202 return ( _data
+ offset
);