framework2

Форк
0
1079 строк · 31.6 Кб
1
#include "ofOpenALSoundPlayer.h"
2

3
#ifdef OF_SOUND_PLAYER_OPENAL
4

5
#define GLM_FORCE_CTOR_INIT
6
#include <glm/gtc/constants.hpp>
7
#include "glm/common.hpp"
8
#include "ofLog.h"
9
#include "ofEvents.h"
10

11
#if defined (TARGET_OF_IOS) || defined (TARGET_OSX)
12
#include <OpenAL/al.h>
13
#include <OpenAL/alc.h>
14
#else
15
#include <AL/al.h>
16
#include <AL/alc.h>
17
#endif
18

19
#ifdef OF_USING_MPG123
20
#include <mpg123.h>
21
#endif
22

23
static ALCdevice * alDevice = nullptr;
24
static ALCcontext * alContext = nullptr;
25
std::vector<float> ofOpenALSoundPlayer::window;
26
float ofOpenALSoundPlayer::windowSum = 0.f;
27

28

29
kiss_fftr_cfg ofOpenALSoundPlayer::systemFftCfg=0;
30
std::vector<float> ofOpenALSoundPlayer::systemWindowedSignal;
31
std::vector<float> ofOpenALSoundPlayer::systemBins;
32
std::vector<kiss_fft_cpx> ofOpenALSoundPlayer::systemCx_out;
33

34
static std::set<ofOpenALSoundPlayer*> & players(){
35
	static std::set<ofOpenALSoundPlayer*> * players = new std::set<ofOpenALSoundPlayer*>;
36
	return *players;
37
}
38

39
void ofOpenALSoundUpdate(){
40
	alcProcessContext(alContext);
41
}
42

43
// ----------------------------------------------------------------------------
44
// from http://devmaster.net/posts/2893/openal-lesson-6-advanced-loading-and-error-handles
45
static std::string getALErrorString(ALenum error) {
46
	switch(error) {
47
        case AL_NO_ERROR:
48
            return "AL_NO_ERROR";
49
        case AL_INVALID_NAME:
50
            return "AL_INVALID_NAME";
51
        case AL_INVALID_ENUM:
52
            return "AL_INVALID_ENUM";
53
        case AL_INVALID_VALUE:
54
            return "AL_INVALID_VALUE";
55
        case AL_INVALID_OPERATION:
56
            return "AL_INVALID_OPERATION";
57
        case AL_OUT_OF_MEMORY:
58
            return "AL_OUT_OF_MEMORY";
59
    };
60
	return "UNKWOWN_ERROR";
61
}
62

63
static std::string getALCErrorString(ALCenum  error) {
64
	switch(error) {
65
        case ALC_NO_ERROR:
66
            return "ALC_NO_ERROR";
67
        case ALC_INVALID_DEVICE:
68
            return "ALC_INVALID_DEVICE";
69
        case ALC_INVALID_CONTEXT:
70
            return "ALC_INVALID_CONTEXT";
71
        case ALC_INVALID_ENUM:
72
            return "ALC_INVALID_ENUM";
73
        case ALC_INVALID_VALUE:
74
            return "ALC_INVALID_VALUE";
75
        case ALC_OUT_OF_MEMORY:
76
            return "ALC_OUT_OF_MEMORY";
77
    };
78
	return "UNKWOWN_ERROR";
79
}
80

81
#ifdef OF_USING_MPG123
82
static std::string getMpg123EncodingString(int encoding) {
83
	switch(encoding) {
84
		case MPG123_ENC_16:
85
			return "MPG123_ENC_16";
86
#if MPG123_API_VERSION>=36
87
		case MPG123_ENC_24:
88
			return "MPG123_ENC_24";
89
#endif
90
		case MPG123_ENC_32:
91
			return "MPG123_ENC_32";
92
		case MPG123_ENC_8:
93
			return "MPG123_ENC_8";
94
		case MPG123_ENC_ALAW_8:
95
			return "MPG123_ENC_ALAW_8";
96
		case MPG123_ENC_FLOAT:
97
			return "MPG123_ENC_FLOAT";
98
		case MPG123_ENC_FLOAT_32:
99
			return "MPG123_ENC_FLOAT_32";
100
		case MPG123_ENC_FLOAT_64:
101
			return "MPG123_ENC_FLOAT_64";
102
		case MPG123_ENC_SIGNED:
103
			return "MPG123_ENC_SIGNED";
104
		case MPG123_ENC_SIGNED_16:
105
			return "MPG123_ENC_SIGNED_16";
106
#if MPG123_API_VERSION>=36
107
		case MPG123_ENC_SIGNED_24:
108
			return "MPG123_ENC_SIGNED_24";
109
#endif
110
		case MPG123_ENC_SIGNED_32:
111
			return "MPG123_ENC_SIGNED_32";
112
		case MPG123_ENC_SIGNED_8:
113
			return "MPG123_ENC_SIGNED_8";
114
		case MPG123_ENC_ULAW_8:
115
			return "MPG123_ENC_ULAW_8";
116
		case MPG123_ENC_UNSIGNED_16:
117
			return "MPG123_ENC_UNSIGNED_16";
118
#if MPG123_API_VERSION>=36
119
		case MPG123_ENC_UNSIGNED_24:
120
			return "MPG123_ENC_UNSIGNED_24";
121
#endif
122
		case MPG123_ENC_UNSIGNED_32:
123
			return "MPG123_ENC_UNSIGNED_32";
124
		case MPG123_ENC_UNSIGNED_8:
125
			return "MPG123_ENC_UNSIGNED_8";
126
		default:
127
			return "MPG123_ENC_ANY";
128
	}
129
}
130
#endif
131

132
#define BUFFER_STREAM_SIZE 4096
133

134
// now, the individual sound player:
135
//------------------------------------------------------------
136
ofOpenALSoundPlayer::ofOpenALSoundPlayer(){
137
	bLoop 			= false;
138
	bLoadedOk 		= false;
139
	pan 			= 0.0f; // range for oF is -1 to 1,
140
	volume 			= 1.0f;
141
	internalFreq 	= 44100;
142
	speed 			= 1;
143
	bPaused 		= false;
144
	isStreaming		= false;
145
	channels		= 0;
146
	duration		= 0;
147
	fftCfg			= 0;
148
	streamf			= 0;
149
#ifdef OF_USING_MPG123
150
	mp3streamf		= 0;
151
#endif
152
	players().insert(this);
153
}
154

155
// ----------------------------------------------------------------------------
156
ofOpenALSoundPlayer::~ofOpenALSoundPlayer(){
157
	unload();
158
	kiss_fftr_free(fftCfg);
159
	players().erase(this);
160
	if( players().empty() ){
161
		close();
162
	}
163
}
164

165
//---------------------------------------
166
// this should only be called once
167
void ofOpenALSoundPlayer::initialize(){
168
	if( !alDevice ){
169
		alDevice = alcOpenDevice( nullptr );
170
		if( !alDevice ){
171
			ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't open OpenAL default device";
172
			return;
173
		}else{
174
			ofLogVerbose("ofOpenALSoundPlayer") << "initialize(): opening "<< alcGetString( alDevice, ALC_DEVICE_SPECIFIER );
175
		}
176
		// Create OpenAL context and make it current. If fails, close the OpenAL device that was just opened.
177
		alContext = alcCreateContext( alDevice, nullptr );
178
		if( !alContext ){
179
			ALCenum err = alcGetError( alDevice ); 
180
			ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't not create OpenAL context: "<< getALCErrorString( err );
181
			close();
182
			return;
183
		}
184

185
		if( alcMakeContextCurrent( alContext )==ALC_FALSE ){
186
			ALCenum err = alcGetError( alDevice ); 
187
			ofLogError("ofOpenALSoundPlayer") << "initialize(): couldn't not make current the create OpenAL context: "<< getALCErrorString( err );
188
			close();
189
			return;
190
		};
191
		alListener3f( AL_POSITION, 0,0,0 );
192
#ifdef OF_USING_MPG123
193
		mpg123_init();
194
#endif
195

196
	}
197
	ofLogVerbose("ofOpenALSoundPlayer") << "initialize(): Done";
198
}
199

200
//---------------------------------------
201
void ofOpenALSoundPlayer::createWindow(int size){
202
	if(int(window.size())!=size){
203
		windowSum = 0;
204
		window.resize(size);
205
		// hanning window
206
		for(int i = 0; i < size; i++){
207
			window[i] = .54 - .46 * cos((glm::two_pi<float>() * i) / (size - 1));
208
			windowSum += window[i];
209
		}
210
	}
211
}
212

213
//---------------------------------------
214
void ofOpenALSoundPlayer::close(){
215
	// Destroy the OpenAL context (if any) before closing the device
216
	if( alDevice ){
217
		if( alContext ){
218
#ifdef OF_USING_MPG123
219
			mpg123_exit();
220
#endif
221
			alcMakeContextCurrent(nullptr);
222
			alcDestroyContext(alContext);
223
			alContext = nullptr;
224
		}
225
		if( alcCloseDevice( alDevice )==ALC_FALSE ){
226
			ofLogNotice("ofOpenALSoundPlayer") << "initialize(): error closing OpenAL device";
227
		}
228
		alDevice = nullptr;
229
	}
230
}
231

232
// ----------------------------------------------------------------------------
233
bool ofOpenALSoundPlayer::sfReadFile(const of::filesystem::path& path, std::vector<short> & buffer, std::vector<float> & fftAuxBuffer){
234
	SF_INFO sfInfo;
235
	SNDFILE* f = sf_open(path.string().c_str(),SFM_READ,&sfInfo);
236
	if(!f){
237
		ofLogError("ofOpenALSoundPlayer") << "sfReadFile(): couldn't read \"" << path << "\"";
238
		return false;
239
	}
240

241
	buffer.resize(sfInfo.frames*sfInfo.channels);
242
	fftAuxBuffer.resize(sfInfo.frames*sfInfo.channels);
243

244
	int subformat = sfInfo.format & SF_FORMAT_SUBMASK ;
245
	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE){
246
		double	scale ;
247
		sf_command (f, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
248
		if (scale < 1e-10)
249
			scale = 1.0 ;
250
		else
251
			scale = 32700.0 / scale ;
252

253
		sf_count_t samples_read = sf_read_float (f, &fftAuxBuffer[0], fftAuxBuffer.size());
254
		if(samples_read<(int)fftAuxBuffer.size()){
255
			ofLogWarning("ofOpenALSoundPlayer") << "sfReadFile(): read " << samples_read << " float samples, expected "
256
			<< fftAuxBuffer.size() << " for \"" << path << "\"";
257
		}
258
		for (int i = 0 ; i < int(fftAuxBuffer.size()) ; i++){
259
			fftAuxBuffer[i] *= scale ;
260
			buffer[i] = 32565.0 * fftAuxBuffer[i];
261
		}
262
	}else{
263
		sf_count_t frames_read = sf_readf_short(f,&buffer[0],sfInfo.frames);
264
		if(frames_read<sfInfo.frames){
265
			ofLogError("ofOpenALSoundPlayer") << "sfReadFile(): read " << frames_read << " frames from buffer, expected "
266
			<< sfInfo.frames << " for \"" << path << "\"";
267
			return false;
268
		}
269
		sf_seek(f,0,SEEK_SET);
270
		frames_read = sf_readf_float(f,&fftAuxBuffer[0],sfInfo.frames);
271
		if(frames_read<sfInfo.frames){
272
			ofLogError("ofOpenALSoundPlayer") << "sfReadFile(): read " << frames_read << " frames from fft buffer, expected "
273
			<< sfInfo.frames << " for \"" << path << "\"";
274
			return false;
275
		}
276
	}
277
	sf_close(f);
278

279
	channels = sfInfo.channels;
280
	duration = float(sfInfo.frames) / float(sfInfo.samplerate);
281
	samplerate = sfInfo.samplerate;
282
	return true;
283
}
284

285
#ifdef OF_USING_MPG123
286
//------------------------------------------------------------
287
bool ofOpenALSoundPlayer::mpg123ReadFile(const of::filesystem::path& path,std::vector<short> & buffer,std::vector<float> & fftAuxBuffer){
288
	int err = MPG123_OK;
289
	mpg123_handle * f = mpg123_new(nullptr,&err);
290
	if(mpg123_open(f,path.string().c_str())!=MPG123_OK){
291
		ofLogError("ofOpenALSoundPlayer") << "mpg123ReadFile(): couldn't read \"" << path << "\"";
292
		return false;
293
	}
294

295
	mpg123_enc_enum encoding;
296
	long int rate;
297
	mpg123_getformat(f,&rate,&channels,(int*)&encoding);
298
	if(encoding!=MPG123_ENC_SIGNED_16){
299
		ofLogError("ofOpenALSoundPlayer") << "mpg123ReadFile(): " << getMpg123EncodingString(encoding)
300
			<< " encoding for \"" << path << "\"" << " unsupported, expecting MPG123_ENC_SIGNED_16";
301
		return false;
302
	}
303
	samplerate = rate;
304

305
	size_t done=0;
306
	size_t buffer_size = mpg123_outblock( f );
307
	buffer.resize(buffer_size/2);
308
	while(mpg123_read(f,(unsigned char*)&buffer[buffer.size()-buffer_size/2],buffer_size,&done)!=MPG123_DONE){
309
		buffer.resize(buffer.size()+buffer_size/2);
310
	};
311
	buffer.resize(buffer.size()-(buffer_size/2-done/2));
312
	mpg123_close(f);
313
	mpg123_delete(f);
314

315
	fftAuxBuffer.resize(buffer.size());
316
	for(int i=0;i<(int)buffer.size();i++){
317
		fftAuxBuffer[i] = float(buffer[i])/32565.f;
318
	}
319
	duration = float(buffer.size()/channels) / float(samplerate);
320
	return true;
321
}
322
#endif
323

324
//------------------------------------------------------------
325
bool ofOpenALSoundPlayer::sfStream(const of::filesystem::path& path,std::vector<short> & buffer,std::vector<float> & fftAuxBuffer){
326
	if(!streamf){
327
		SF_INFO sfInfo;
328
		streamf = sf_open(path.string().c_str(),SFM_READ,&sfInfo);
329
		if(!streamf){
330
			ofLogError("ofOpenALSoundPlayer") << "sfStream(): couldn't read \"" << path << "\"";
331
			return false;
332
		}
333

334
		stream_subformat = sfInfo.format & SF_FORMAT_SUBMASK ;
335
		if (stream_subformat == SF_FORMAT_FLOAT || stream_subformat == SF_FORMAT_DOUBLE){
336
			sf_command (streamf, SFC_CALC_SIGNAL_MAX, &stream_scale, sizeof (stream_scale)) ;
337
			if (stream_scale < 1e-10)
338
				stream_scale = 1.0 ;
339
			else
340
				stream_scale = 32700.0 / stream_scale ;
341
		}
342
		channels = sfInfo.channels;
343
		duration = float(sfInfo.frames) / float(sfInfo.samplerate);
344
		samplerate = sfInfo.samplerate;
345
		stream_samples_read = 0;
346
	}
347

348
	int curr_buffer_size = BUFFER_STREAM_SIZE*channels;
349
	if(speed>1) curr_buffer_size *= (int)round(speed);
350
	buffer.resize(curr_buffer_size);
351
	fftAuxBuffer.resize(buffer.size());
352
	if (stream_subformat == SF_FORMAT_FLOAT || stream_subformat == SF_FORMAT_DOUBLE){
353
		sf_count_t samples_read = sf_read_float (streamf, &fftAuxBuffer[0], fftAuxBuffer.size());
354
		stream_samples_read += samples_read;
355
		if(samples_read<(int)fftAuxBuffer.size()){
356
			fftAuxBuffer.resize(samples_read);
357
			buffer.resize(samples_read);
358
			setPosition(0);
359
			if(!bLoop) stopThread();
360
			stream_samples_read = 0;
361
			stream_end = true;
362
		}
363
		for (int i = 0 ; i < int(fftAuxBuffer.size()) ; i++){
364
			fftAuxBuffer[i] *= stream_scale ;
365
			buffer[i] = 32565.0 * fftAuxBuffer[i];
366
		}
367
	}else{
368
		sf_count_t frames_read = sf_readf_short(streamf,&buffer[0],curr_buffer_size/channels);
369
		stream_samples_read += frames_read*channels;
370
		if(frames_read<curr_buffer_size/channels){
371
			fftAuxBuffer.resize(frames_read*channels);
372
			buffer.resize(frames_read*channels);
373
			setPosition(0);
374
			if(!bLoop) stopThread();
375
			stream_samples_read = 0;
376
			stream_end = true;
377
		}
378
		for(int i=0;i<(int)buffer.size();i++){
379
			fftAuxBuffer[i]=float(buffer[i])/32565.0f;
380
		}
381
	}
382

383
	return true;
384
}
385

386
#ifdef OF_USING_MPG123
387
//------------------------------------------------------------
388
bool ofOpenALSoundPlayer::mpg123Stream(const of::filesystem::path& path,std::vector<short> & buffer,std::vector<float> & fftAuxBuffer){
389
	if(!mp3streamf){
390
		int err = MPG123_OK;
391
		mp3streamf = mpg123_new(nullptr,&err);
392
		if(mpg123_open(mp3streamf,path.string().c_str())!=MPG123_OK){
393
			mpg123_close(mp3streamf);
394
			mpg123_delete(mp3streamf);
395
			ofLogError("ofOpenALSoundPlayer") << "mpg123Stream(): couldn't read \"" << path << "\"";
396
			return false;
397
		}
398

399
		long int rate;
400
		mpg123_getformat(mp3streamf,&rate,&channels,(int*)&stream_encoding);
401
		if(stream_encoding!=MPG123_ENC_SIGNED_16){
402
			ofLogError("ofOpenALSoundPlayer") << "mpg123Stream(): " << getMpg123EncodingString(stream_encoding)
403
			<< " encoding for \"" << path << "\"" << " unsupported, expecting MPG123_ENC_SIGNED_16";
404
			return false;
405
		}
406
		samplerate = rate;
407
		mp3_buffer_size = mpg123_outblock( mp3streamf );
408

409

410
		mpg123_seek(mp3streamf,0,SEEK_END);
411
		off_t samples = mpg123_tell(mp3streamf);
412
		duration = float(samples/channels) / float(samplerate);
413
		mpg123_seek(mp3streamf,0,SEEK_SET);
414
	}
415

416
	int curr_buffer_size = mp3_buffer_size;
417
	if(speed>1) curr_buffer_size *= (int)round(speed);
418
	buffer.resize(curr_buffer_size);
419
	fftAuxBuffer.resize(buffer.size());
420
	size_t done=0;
421
	if(mpg123_read(mp3streamf,(unsigned char*)&buffer[0],curr_buffer_size*2,&done)==MPG123_DONE){
422
		setPosition(0);
423
		buffer.resize(done/2);
424
		fftAuxBuffer.resize(done/2);
425
		if(!bLoop) stopThread();
426
		stream_end = true;
427
	}
428

429

430
	for(int i=0;i<(int)buffer.size();i++){
431
		fftAuxBuffer[i] = float(buffer[i])/32565.f;
432
	}
433

434
	return true;
435
}
436
#endif
437

438
//------------------------------------------------------------
439
bool ofOpenALSoundPlayer::stream(const of::filesystem::path& fileName, std::vector<short> & buffer){
440
#ifdef OF_USING_MPG123
441
	if(ofFilePath::getFileExt(fileName)=="mp3" || ofFilePath::getFileExt(fileName)=="MP3" || mp3streamf){
442
		if(!mpg123Stream(fileName,buffer,fftAuxBuffer)) return false;
443
	}else
444
#endif
445
		if(!sfStream(fileName,buffer,fftAuxBuffer)) return false;
446

447
	fftBuffers.resize(channels);
448
	int numFrames = buffer.size()/channels;
449

450
	for(int i=0;i<channels;i++){
451
		fftBuffers[i].resize(numFrames);
452
		for(int j=0;j<numFrames;j++){
453
			fftBuffers[i][j] = fftAuxBuffer[j*channels+i];
454
		}
455
	}
456
	return true;
457
}
458

459
bool ofOpenALSoundPlayer::readFile(const of::filesystem::path& fileName, std::vector<short> & buffer){
460
#ifdef OF_USING_MPG123
461
	if(ofFilePath::getFileExt(fileName)!="mp3" && ofFilePath::getFileExt(fileName)!="MP3"){
462
		if(!sfReadFile(fileName,buffer,fftAuxBuffer)) return false;
463
	}else{
464
		if(!mpg123ReadFile(fileName,buffer,fftAuxBuffer)) return false;
465
	}
466
#else
467
	if(!sfReadFile(fileName,buffer,fftAuxBuffer)) return false;
468
#endif
469
	fftBuffers.resize(channels);
470
	int numFrames = buffer.size()/channels;
471

472
	for(int i=0;i<channels;i++){
473
		fftBuffers[i].resize(numFrames);
474
		for(int j=0;j<numFrames;j++){
475
			fftBuffers[i][j] = fftAuxBuffer[j*channels+i];
476
		}
477
	}
478
	return true;
479
}
480

481
//------------------------------------------------------------
482
bool ofOpenALSoundPlayer::load(const of::filesystem::path& _fileName, bool is_stream){
483

484
	auto fileName = ofToDataPath(_fileName);
485

486
	bMultiPlay = false;
487
	isStreaming = is_stream;
488
	int err = AL_NO_ERROR;
489

490
	// [1] init sound systems, if necessary
491
	initialize();
492

493
	// [2] try to unload any previously loaded sounds
494
	// & prevent user-created memory leaks
495
	// if they call "loadSound" repeatedly, for example
496

497
	unload();
498
	ALenum format=AL_FORMAT_MONO16;
499
	bLoadedOk = false;
500

501
	if(!isStreaming){
502
		bLoadedOk = readFile(fileName, buffer);
503
	}else{
504
		bLoadedOk = stream(fileName, buffer);
505
	}
506
	if( !bLoadedOk ) {
507
		ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't read \"" << fileName << "\"";
508
		return false;
509
	}
510

511
	int numFrames = buffer.size()/channels;
512

513
	if(isStreaming){
514
		buffers.resize(channels*2);
515
	}else{
516
		buffers.resize(channels);
517
	}
518
	alGenBuffers(buffers.size(), &buffers[0]);
519
	if(channels==1){
520
		sources.resize(1);
521
		alGetError(); // Clear error.
522
		alGenSources(1, &sources[0]);
523
		err = alGetError();
524
		if (err != AL_NO_ERROR){
525
			ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't generate source for \"" << fileName << "\": "
526
			<< (int) err << " " << getALErrorString(err);
527
			return false;
528
		}
529

530
		for(int i=0; i<(int)buffers.size(); i++){
531
			alGetError(); // Clear error.
532
			alBufferData(buffers[i],format,&buffer[0],buffer.size()*2,samplerate);
533
			err = alGetError();
534
			if (err != AL_NO_ERROR){
535
				ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create buffer for \"" << fileName << "\": "
536
				<< (int) err << " " << getALErrorString(err);
537
				return false;
538
			}
539
			if(isStreaming){
540
				stream(fileName,buffer);
541
			}
542
		}
543
		if(isStreaming){
544
			alSourceQueueBuffers(sources[0],buffers.size(),&buffers[0]);
545
		}else{
546
			alSourcei (sources[0], AL_BUFFER,   buffers[0]);
547
		}
548

549
		alSourcef (sources[0], AL_PITCH,    1.0f);
550
		alSourcef (sources[0], AL_GAIN,     1.0f);
551
	    alSourcef (sources[0], AL_ROLLOFF_FACTOR,  0.0);
552
	    alSourcei (sources[0], AL_SOURCE_RELATIVE, AL_TRUE);
553
	}else{
554
		std::vector<std::vector<short> > multibuffer;
555
		multibuffer.resize(channels);
556
		sources.resize(channels);
557
		alGenSources(channels, &sources[0]);
558
		if(isStreaming){
559
			for(int s=0; s<2;s++){
560
				for(int i=0;i<channels;i++){
561
					multibuffer[i].resize(buffer.size()/channels);
562
					for(int j=0;j<numFrames;j++){
563
						multibuffer[i][j] = buffer[j*channels+i];
564
					}
565
					alGetError(); // Clear error.
566
					alBufferData(buffers[s*2+i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate);
567
					err = alGetError();
568
					if ( err != AL_NO_ERROR){
569
						ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo buffers for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err);
570
						return false;
571
					}
572
					alSourceQueueBuffers(sources[i],1,&buffers[s*2+i]);
573
					stream(fileName,buffer);
574
				}
575
			}
576
		}else{
577
			for(int i=0;i<channels;i++){
578
				multibuffer[i].resize(buffer.size()/channels);
579
				for(int j=0;j<numFrames;j++){
580
					multibuffer[i][j] = buffer[j*channels+i];
581
				}
582
				alGetError(); // Clear error.
583
				alBufferData(buffers[i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate);
584
				err = alGetError();
585
				if (err != AL_NO_ERROR){
586
					ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo buffers for \"" << fileName << "\": "
587
					<< (int) err << " " << getALErrorString(err);
588
					return false;
589
				}
590
				alSourcei (sources[i], AL_BUFFER,   buffers[i]   );
591
			}
592
		}
593

594

595
		for(int i=0;i<channels;i++){
596
			err = alGetError();
597
			if (err != AL_NO_ERROR){
598
				ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo sources for \"" << fileName << "\": "
599
				<< (int) err << " " << getALErrorString(err);
600
				return false;
601
			}
602

603
			// only stereo panning
604
			if(i==0){
605
				float pos[3] = {-1,0,0};
606
				alSourcefv(sources[i],AL_POSITION,pos);
607
			}else{
608
				float pos[3] = {1,0,0};
609
				alSourcefv(sources[i],AL_POSITION,pos);
610
			}
611
			alSourcef (sources[i], AL_ROLLOFF_FACTOR,  0.0);
612
			alSourcei (sources[i], AL_SOURCE_RELATIVE, AL_TRUE);
613
		}
614
	}
615

616
	bLoadedOk = true;
617
	return bLoadedOk;
618

619
}
620

621
//------------------------------------------------------------
622
bool ofOpenALSoundPlayer::isLoaded() const{
623
	return bLoadedOk;
624
}
625

626
//------------------------------------------------------------
627
void ofOpenALSoundPlayer::threadedFunction(){
628
	std::vector<std::vector<short> > multibuffer;
629
	multibuffer.resize(channels);
630
	while(isThreadRunning()){
631
		std::unique_lock<std::mutex> lock(mutex);
632
		for(int i=0; i<int(sources.size())/channels; i++){
633
			int processed;
634
			alGetSourcei(sources[i*channels], AL_BUFFERS_PROCESSED, &processed);
635

636
			while(processed--)
637
			{
638
				stream("",buffer);
639
				int numFrames = buffer.size()/channels;
640
				if(channels>1){
641
					for(int j=0;j<channels;j++){
642
						multibuffer[j].resize(buffer.size()/channels);
643
						for(int k=0;k<numFrames;k++){
644
							multibuffer[j][k] = buffer[k*channels+j];
645
						}
646
						ALuint albuffer;
647
						alSourceUnqueueBuffers(sources[i*channels+j], 1, &albuffer);
648
						alBufferData(albuffer,AL_FORMAT_MONO16,&multibuffer[j][0],buffer.size()*2/channels,samplerate);
649
						alSourceQueueBuffers(sources[i*channels+j], 1, &albuffer);
650
					}
651
				}else{
652
					ALuint albuffer;
653
					alSourceUnqueueBuffers(sources[i], 1, &albuffer);
654
					alBufferData(albuffer,AL_FORMAT_MONO16,&buffer[0],buffer.size()*2/channels,samplerate);
655
					alSourceQueueBuffers(sources[i], 1, &albuffer);
656
				}
657
				if(stream_end){
658
					break;
659
				}
660
			}
661
			ALint state;
662
			alGetSourcei(sources[i*channels],AL_SOURCE_STATE,&state);
663
			bool stream_running=false;
664
			#ifdef OF_USING_MPG123
665
				stream_running = streamf || mp3streamf;
666
			#else
667
				stream_running = streamf;
668
			#endif
669
			if(state != AL_PLAYING && stream_running && !stream_end){
670
				alSourcePlayv(channels,&sources[i*channels]);
671
			}
672

673
			stream_end = false;
674
		}
675
		sleep(1);
676
	}
677
}
678

679
//------------------------------------------------------------
680
void ofOpenALSoundPlayer::update(ofEventArgs & args){
681

682
	for(int i=1; i<int(sources.size())/channels; ){
683
		ALint state;
684
		alGetSourcei(sources[i*channels],AL_SOURCE_STATE,&state);
685
		if(state != AL_PLAYING){
686
			alDeleteSources(channels,&sources[i*channels]);
687
			for(int j=0;j<channels;j++){
688
				sources.erase(sources.begin()+i*channels);
689
			}
690
		}else{
691
			i++;
692
		}
693
	}
694
}
695

696
//------------------------------------------------------------
697
void ofOpenALSoundPlayer::unload(){
698
	stop();
699
	ofRemoveListener(ofEvents().update,this,&ofOpenALSoundPlayer::update);
700

701
	// Only lock the thread where necessary.
702
	{
703
		std::unique_lock<std::mutex> lock(mutex);
704

705
		// Delete sources before buffers.
706
		alDeleteSources(sources.size(),&sources[0]);
707
		alDeleteBuffers(buffers.size(),&buffers[0]);
708

709
		sources.clear();
710
		buffers.clear();
711
	}
712

713
	// Free resources and close file descriptors.
714
#ifdef OF_USING_MPG123
715
	if(mp3streamf){
716
		mpg123_close(mp3streamf);
717
		mpg123_delete(mp3streamf);
718
	}
719
	mp3streamf = 0;
720
#endif
721

722
	if(streamf){
723
		sf_close(streamf);
724
	}
725
	streamf = 0;
726

727
	bLoadedOk = false;
728
}
729

730
//------------------------------------------------------------
731
bool ofOpenALSoundPlayer::isPlaying() const{
732
	if(sources.empty()) return false;
733
	if(isStreaming) return isThreadRunning();
734
	ALint state;
735
	bool playing=false;
736
	for(int i=0;i<(int)sources.size();i++){
737
		alGetSourcei(sources[i],AL_SOURCE_STATE,&state);
738
		playing |= (state == AL_PLAYING);
739
	}
740
	return playing;
741
}
742

743
//------------------------------------------------------------
744
bool ofOpenALSoundPlayer::isPaused() const{
745
	if(sources.empty()) return false;
746
	ALint state;
747
	bool paused=true;
748
	for(int i=0;i<(int)sources.size();i++){
749
		alGetSourcei(sources[i],AL_SOURCE_STATE,&state);
750
		paused &= (state == AL_PAUSED);
751
	}
752
	return paused;
753
}
754

755
//------------------------------------------------------------
756
float ofOpenALSoundPlayer::getSpeed() const{
757
	return speed;
758
}
759

760
//------------------------------------------------------------
761
float ofOpenALSoundPlayer::getPan() const{
762
	return pan;
763
}
764

765
//------------------------------------------------------------
766
float ofOpenALSoundPlayer::getVolume() const{
767
	return volume;
768
}
769

770
//------------------------------------------------------------
771
void ofOpenALSoundPlayer::setVolume(float vol){
772
	volume = vol;
773
	if(sources.empty()) return;
774
	if(channels==1){
775
		alSourcef (sources[sources.size()-1], AL_GAIN, vol);
776
	}else{
777
		setPan(pan);
778
	}
779
}
780

781
//------------------------------------------------------------
782
void ofOpenALSoundPlayer::setPosition(float pct){
783
	setPositionMS(duration*pct*1000.f);
784
}
785

786
//------------------------------------------------------------
787
void ofOpenALSoundPlayer::setPositionMS(int ms){
788
	if(sources.empty()) return;
789
#ifdef OF_USING_MPG123
790
	if(mp3streamf){
791
		mpg123_seek(mp3streamf,float(ms)/1000.f*samplerate,SEEK_SET);
792
	}else
793
#endif
794
	if(streamf){
795
        stream_samples_read = sf_seek(streamf,float(ms)/1000.f*samplerate,SEEK_SET) * channels;
796
	}else{
797
		for(int i=0;i<(int)channels;i++){
798
			alSourcef(sources[sources.size()-channels+i],AL_SEC_OFFSET,float(ms)/1000.f);
799
		}
800
	}
801
}
802

803
//------------------------------------------------------------
804
float ofOpenALSoundPlayer::getPosition() const{
805
	if(duration==0 || sources.empty())
806
		return 0;
807
	else
808
		return getPositionMS()/(1000.f*duration);
809
}
810

811
//------------------------------------------------------------
812
int ofOpenALSoundPlayer::getPositionMS() const{
813
	if(sources.empty()) return 0;
814
	float pos;
815
#ifdef OF_USING_MPG123
816
	if(mp3streamf){
817
		pos = float(mpg123_tell(mp3streamf)) / float(samplerate);
818
	}else
819
#endif
820
	if(streamf){
821
		pos = float(stream_samples_read) / float(channels) / float(samplerate);
822
	}else{
823
		alGetSourcef(sources[sources.size()-1],AL_SEC_OFFSET,&pos);
824
	}
825
	return pos * 1000.f;
826
}
827

828
//------------------------------------------------------------
829
void ofOpenALSoundPlayer::setPan(float p){
830
	if(sources.empty()) return;
831
	p = glm::clamp(p, -1.f, 1.f);
832
	pan = p;
833
	if(channels==1){
834
		float pos[3] = {p,0,0};
835
		alSourcefv(sources[sources.size()-1],AL_POSITION,pos);
836
	}else{
837
        // calculates left/right volumes from pan-value (constant panning law)
838
        // see: Curtis Roads: Computer Music Tutorial p 460
839
		// thanks to jasch
840
		
841
        float angle = p * glm::quarter_pi<float>(); // in radians from -45. to +45.
842
        float cosAngle = cos(angle);
843
        float sinAngle = sin(angle);
844

845
		float leftVol  = (cosAngle - sinAngle) * glm::one_over_root_two<float>(); //// multiplied by 1/sqrt(2)
846
		float rightVol = (cosAngle + sinAngle) * glm::one_over_root_two<float>(); // multiplied by 1/sqrt(2)
847
		for(int i=0;i<(int)channels;i++){
848
			if(i==0){
849
				alSourcef(sources[sources.size()-channels+i],AL_GAIN,leftVol*volume);
850
			}else{
851
				alSourcef(sources[sources.size()-channels+i],AL_GAIN,rightVol*volume);
852
			}
853
		}
854
	}
855
}
856

857

858
//------------------------------------------------------------
859
void ofOpenALSoundPlayer::setPaused(bool bP){
860
	if(sources.empty()) return;
861
	std::unique_lock<std::mutex> lock(mutex);
862
	if(bP){
863
		alSourcePausev(sources.size(),&sources[0]);
864
		if(isStreaming){
865
			stopThread();
866
		}
867
	}else{
868
		alSourcePlayv(sources.size(),&sources[0]);
869
		if(isStreaming){
870
			startThread();
871
		}
872
	}
873

874
	bPaused = bP;
875
}
876

877

878
//------------------------------------------------------------
879
void ofOpenALSoundPlayer::setSpeed(float spd){
880
	for(int i=0;i<channels;i++){
881
		alSourcef(sources[sources.size()-channels+i],AL_PITCH,spd);
882
	}
883
	speed = spd;
884
}
885

886

887
//------------------------------------------------------------
888
void ofOpenALSoundPlayer::setLoop(bool bLp){
889
	if(bMultiPlay) return; // no looping on multiplay
890
	bLoop = bLp;
891
	if(isStreaming) return;
892
	for(int i=0;i<(int)sources.size();i++){
893
		alSourcei(sources[i],AL_LOOPING,bLp?AL_TRUE:AL_FALSE);
894
	}
895
}
896

897
// ----------------------------------------------------------------------------
898
void ofOpenALSoundPlayer::setMultiPlay(bool bMp){
899
	if(isStreaming && bMp){
900
		ofLogWarning("ofOpenALSoundPlayer") << "setMultiPlay(): sorry, no support for multiplay streams";
901
		return;
902
	}
903
	bMultiPlay = bMp;		// be careful with this...
904
	if(sources.empty()) return;
905
	if(bMultiPlay){
906
		ofAddListener(ofEvents().update,this,&ofOpenALSoundPlayer::update);
907
	}else{
908
		ofRemoveListener(ofEvents().update,this,&ofOpenALSoundPlayer::update);
909
	}
910
}
911

912
// ----------------------------------------------------------------------------
913
void ofOpenALSoundPlayer::play(){
914
	std::unique_lock<std::mutex> lock(mutex);
915
	int err = alGetError();
916

917
	// if the sound is set to multiplay, then create new sources,
918
	// do not multiplay on loop or we won't be able to stop it
919
	if (bMultiPlay && !bLoop){
920
		sources.resize(sources.size()+channels);
921
		alGetError(); // Clear error.
922
		alGenSources(channels, &sources[sources.size()-channels]);
923
		err = alGetError();
924
		if (err != AL_NO_ERROR){
925
			ofLogError("ofOpenALSoundPlayer") << "play(): couldn't create multiplay stereo sources: "
926
			<< (int) err << " " << getALErrorString(err);
927
			return;
928
		}
929
		for(int i=0;i<channels;i++){
930
			alSourcei (sources[sources.size()-channels+i], AL_BUFFER,   buffers[i]   );
931
			// only stereo panning
932
			if(i==0){
933
				float pos[3] = {-1,0,0};
934
				alSourcefv(sources[sources.size()-channels+i],AL_POSITION,pos);
935
			}else{
936
				float pos[3] = {1,0,0};
937
				alSourcefv(sources[sources.size()-channels+i],AL_POSITION,pos);
938
			}
939
		    alSourcef (sources[sources.size()-channels+i], AL_ROLLOFF_FACTOR,  0.0);
940
		    alSourcei (sources[sources.size()-channels+i], AL_SOURCE_RELATIVE, AL_TRUE);
941
		}
942

943
		err = alGetError();
944
		if (err != AL_NO_ERROR){
945
			ofLogError("ofOpenALSoundPlayer") << "play(): couldn't assign multiplay buffers: "
946
			<< (int) err << " " << getALErrorString(err);
947
			return;
948
		}
949
	}
950
	alSourcePlayv(channels,&sources[sources.size()-channels]);
951

952
	if(bMultiPlay){
953
		ofAddListener(ofEvents().update,this,&ofOpenALSoundPlayer::update);
954
	}
955
	if(isStreaming){
956
		setPosition(0);
957
		stream_end = false;
958
		startThread();
959
	}
960

961
}
962

963
// ----------------------------------------------------------------------------
964
void ofOpenALSoundPlayer::stop(){
965
	if(sources.empty()) return;
966
	std::unique_lock<std::mutex> lock(mutex);
967
	alSourceStopv(channels,&sources[sources.size()-channels]);
968
	if(isStreaming){
969
		setPosition(0);
970
		stopThread();
971
	}
972
}
973

974
// ----------------------------------------------------------------------------
975
void ofOpenALSoundPlayer::initFFT(int bands){
976
	if(int(bins.size())==bands) return;
977
	int signalSize = (bands-1)*2;
978
	if(fftCfg!=0) kiss_fftr_free(fftCfg);
979
	fftCfg = kiss_fftr_alloc(signalSize, 0, nullptr, nullptr);
980
	cx_out.resize(bands);
981
	bins.resize(bands);
982
	createWindow(signalSize);
983
}
984

985
// ----------------------------------------------------------------------------
986
void ofOpenALSoundPlayer::initSystemFFT(int bands){
987
	if(int(systemBins.size())==bands) return;
988
	int signalSize = (bands-1)*2;
989
	if(systemFftCfg!=0) kiss_fftr_free(systemFftCfg);
990
	systemFftCfg = kiss_fftr_alloc(signalSize, 0, nullptr, nullptr);
991
	systemCx_out.resize(bands);
992
	systemBins.resize(bands);
993
	createWindow(signalSize);
994
}
995

996
float * ofOpenALSoundPlayer::getCurrentBufferSum(int size){
997
	if(int(windowedSignal.size())!=size){
998
		windowedSignal.resize(size);
999
	}
1000
	windowedSignal.assign(windowedSignal.size(),0);
1001
	for(int k=0;k<int(sources.size())/channels;k++){
1002
		if(!isStreaming){
1003
			ALint state;
1004
			alGetSourcei(sources[k*channels],AL_SOURCE_STATE,&state);
1005
			if( state != AL_PLAYING ) continue;
1006
		}
1007
		int pos;
1008
		alGetSourcei(sources[k*channels],AL_SAMPLE_OFFSET,&pos);
1009
		//if(pos+size>=(int)fftBuffers[0].size()) continue;
1010
		for(int i=0;i<channels;i++){
1011
			float gain;
1012
			alGetSourcef(sources[k*channels+i],AL_GAIN,&gain);
1013
			for(int j=0;j<size;j++){
1014
				if(pos+j<(int)fftBuffers[i].size())
1015
					windowedSignal[j]+=fftBuffers[i][pos+j]*gain;
1016
				else
1017
					windowedSignal[j]=0;
1018
			}
1019
		}
1020
	}
1021
	return &windowedSignal[0];
1022
}
1023

1024
// ----------------------------------------------------------------------------
1025
float * ofOpenALSoundPlayer::getSpectrum(int bands){
1026
	initFFT(bands);
1027
	bins.assign(bins.size(),0);
1028
	if(sources.empty()) return &bins[0];
1029

1030
	int signalSize = (bands-1)*2;
1031
	getCurrentBufferSum(signalSize);
1032

1033
	float normalizer = 2. / windowSum;
1034
	runWindow(windowedSignal);
1035
	kiss_fftr(fftCfg, &windowedSignal[0], &cx_out[0]);
1036
	for(int i= 0; i < bands; i++) {
1037
		bins[i] += sqrtf(cx_out[i].r * cx_out[i].r + cx_out[i].i * cx_out[i].i) * normalizer;
1038
	}
1039
	return &bins[0];
1040
}
1041

1042
// ----------------------------------------------------------------------------
1043
float * ofOpenALSoundPlayer::getSystemSpectrum(int bands){
1044
	initSystemFFT(bands);
1045
	systemBins.assign(systemBins.size(),0);
1046
	if(players().empty()) return &systemBins[0];
1047

1048
	int signalSize = (bands-1)*2;
1049
	if(int(systemWindowedSignal.size())!=signalSize){
1050
		systemWindowedSignal.resize(signalSize);
1051
	}
1052
	systemWindowedSignal.assign(systemWindowedSignal.size(),0);
1053

1054
	std::set<ofOpenALSoundPlayer*>::iterator it;
1055
	for(it=players().begin();it!=players().end();it++){
1056
		if(!(*it)->isPlaying()) continue;
1057
		float * buffer = (*it)->getCurrentBufferSum(signalSize);
1058
		for(int i=0;i<signalSize;i++){
1059
			systemWindowedSignal[i]+=buffer[i];
1060
		}
1061
	}
1062

1063
	float normalizer = 2. / windowSum;
1064
	runWindow(systemWindowedSignal);
1065
	kiss_fftr(systemFftCfg, &systemWindowedSignal[0], &systemCx_out[0]);
1066
	for(int i= 0; i < bands; i++) {
1067
		systemBins[i] += sqrtf(systemCx_out[i].r * systemCx_out[i].r + systemCx_out[i].i * systemCx_out[i].i) * normalizer;
1068
	}
1069
	return &systemBins[0];
1070
}
1071

1072
// ----------------------------------------------------------------------------
1073
void ofOpenALSoundPlayer::runWindow(std::vector<float> & signal){
1074
	for(int i = 0; i < (int)signal.size(); i++)
1075
		signal[i] *= window[i];
1076
}
1077

1078

1079
#endif
1080

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.