44 audio_debug(
"FmodAudioSound::FmodAudioSound() Creating new sound, filename: " 47 _active = manager->get_active();
64 _max_dist = 1000000000.0;
71 for (
int i=0; i<AudioManager::SPK_COUNT; i++) {
77 DCAST_INTO_V(fmanager, manager);
85 result = _manager->_system->getSpeakerMode( &_speakermode );
86 fmod_audio_errcheck(
"_system->getSpeakerMode()", result);
89 bool preload = (fmod_audio_preload_threshold < 0) || (file->
get_file_size() < fmod_audio_preload_threshold);
90 int flags = FMOD_SOFTWARE;
91 flags |= positional ? FMOD_3D : FMOD_2D;
93 FMOD_CREATESOUNDEXINFO sound_info;
94 memset(&sound_info, 0,
sizeof(sound_info));
95 sound_info.cbsize =
sizeof(sound_info);
100 memcpy(&sound_info, &_manager->_midi_info,
sizeof(sound_info));
101 if (sound_info.dlsname !=
nullptr) {
102 audio_debug(
"Using DLS file " << sound_info.dlsname);
106 const char *name_or_data = _file_name.c_str();
109 vector_uchar mem_buffer;
116 sound_info.length = mem_buffer.size();
117 if (mem_buffer.size() != 0) {
118 name_or_data = (
const char *)&mem_buffer[0];
120 flags |= FMOD_OPENMEMORY;
121 if (fmodAudio_cat.is_debug()) {
122 fmodAudio_cat.debug()
123 <<
"Reading " << _file_name <<
" into memory (" << sound_info.length
132 os_filename = info.get_filename().to_os_specific();
133 name_or_data = os_filename.c_str();
134 sound_info.fileoffset = (
unsigned int)info.get_start();
135 sound_info.length = (
unsigned int)info.get_size();
136 flags |= FMOD_CREATESTREAM;
137 if (fmodAudio_cat.is_debug()) {
138 fmodAudio_cat.debug()
139 <<
"Streaming " << _file_name <<
" from disk (" << name_or_data
140 <<
", " << sound_info.fileoffset <<
", " << sound_info.length <<
")\n";
144 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) 147 name_or_data = (
const char *)file;
148 sound_info.length = (
unsigned int)info.get_size();
149 sound_info.useropen = open_callback;
150 sound_info.userclose = close_callback;
151 sound_info.userread = read_callback;
152 sound_info.userseek = seek_callback;
153 flags |= FMOD_CREATESTREAM;
154 if (fmodAudio_cat.is_debug()) {
155 fmodAudio_cat.debug()
156 <<
"Streaming " << _file_name <<
" from disk using callbacks\n";
159 #else // HAVE_THREADS && !SIMPLE_THREADS 163 fmodAudio_cat.warning()
164 <<
"Cannot stream " << _file_name <<
"; file is not literally on disk.\n";
169 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
172 if (result != FMOD_OK) {
173 audio_error(
"createSound(" << _file_name <<
"): " << FMOD_ErrorString(result));
176 FMOD_CREATESOUNDEXINFO sound_info;
177 memset(&sound_info, 0,
sizeof(sound_info));
178 char blank_data[100];
179 memset(blank_data, 0,
sizeof(blank_data));
180 sound_info.cbsize =
sizeof(sound_info);
181 sound_info.length =
sizeof(blank_data);
182 sound_info.numchannels = 1;
183 sound_info.defaultfrequency = 8000;
184 sound_info.format = FMOD_SOUND_FORMAT_PCM16;
185 int flags = FMOD_SOFTWARE | FMOD_OPENMEMORY | FMOD_OPENRAW;
187 result = _manager->_system->createSound( blank_data, flags, &sound_info, &_sound);
188 fmod_audio_errcheck(
"createSound (blank)", result);
193 _sound->setLoopCount(1);
194 _sound->setMode(FMOD_LOOP_OFF);
201 result = _sound->getDefaults( &_sampleFrequency, &_volume , &_balance, &_priority);
202 fmod_audio_errcheck(
"_sound->getDefaults()", result);
215 _manager->_all_sounds.erase(
this);
218 result = _sound->release();
219 fmod_audio_errcheck(
"_sound->release()", result);
240 result =_channel->stop();
241 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
243 }
else if (result == FMOD_OK) {
246 fmod_audio_errcheck(
"_channel->stop()", result);
285 audio_debug(
"FmodAudioSound::set_loop_count() Setting the sound's loop count to: " << loop_count);
290 if (loop_count == 0) {
291 result = _sound->setLoopCount( -1 );
292 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
293 result =_sound->setMode(FMOD_LOOP_NORMAL);
294 fmod_audio_errcheck(
"_sound->setMode()", result);
295 }
else if (loop_count == 1) {
296 result = _sound->setLoopCount( 1 );
297 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
298 result =_sound->setMode(FMOD_LOOP_OFF);
299 fmod_audio_errcheck(
"_sound->setMode()", result);
301 result = _sound->setLoopCount( loop_count );
302 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
303 result =_sound->setMode(FMOD_LOOP_NORMAL);
304 fmod_audio_errcheck(
"_sound->setMode()", result);
307 audio_debug(
"FmodAudioSound::set_loop_count() Sound's loop count should be set to: " << loop_count);
319 result = _sound->getLoopCount( &loop_count );
320 fmod_audio_errcheck(
"_sound->getLoopCount()", result);
322 if (loop_count <= 0) {
325 return (
unsigned long)loop_count;
336 _start_time = start_time;
338 if (
status() == PLAYING) {
351 unsigned int current_time;
357 result = _channel->getPosition( ¤t_time , FMOD_TIMEUNIT_MS );
358 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
361 fmod_audio_errcheck(
"_channel->getPosition()", result);
363 return ((
double)current_time) / 1000.0;
373 set_volume_on_channel();
387 void FmodAudioSound::
397 int startTime = (int)(_start_time * 1000);
401 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
402 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
406 fmod_audio_errcheck(
"_channel->setPosition()", result);
409 result = _channel->isPlaying(&playing);
410 fmod_audio_errcheck(
"_channel->isPlaying()", result);
411 if (result != FMOD_OK || !playing) {
418 result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound,
true, &_channel);
419 fmod_audio_errcheck(
"_system->playSound()", result);
420 result = _channel->setChannelGroup(_manager->_channelgroup);
421 fmod_audio_errcheck(
"_channel->setChannelGroup()", result);
422 result = _channel->setUserData(
this);
423 fmod_audio_errcheck(
"_channel->setUserData()", result);
424 result = _channel->setCallback(sound_end_callback);
425 fmod_audio_errcheck(
"_channel->setCallback()", result);
426 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
427 fmod_audio_errcheck(
"_channel->setPosition()", result);
429 set_volume_on_channel();
430 set_play_rate_on_channel();
431 set_speaker_mix_or_balance_on_channel();
433 set_3d_attributes_on_channel();
435 result = _channel->setPaused(
false);
436 fmod_audio_errcheck(
"_channel->setPaused()", result);
445 void FmodAudioSound::
446 set_volume_on_channel() {
451 result = _channel->setVolume( _volume );
452 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
455 fmod_audio_errcheck(
"_channel->setVolume()", result);
467 set_speaker_mix_or_balance_on_channel();
490 set_play_rate_on_channel();
496 PN_stdfloat FmodAudioSound::
497 get_play_rate()
const {
504 void FmodAudioSound::
505 set_play_rate_on_channel() {
508 PN_stdfloat frequency = _sampleFrequency * _playrate;
511 result = _channel->setFrequency( frequency );
512 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
515 fmod_audio_errcheck(
"_channel->setFrequency()", result);
537 result = _sound->getLength( &
length, FMOD_TIMEUNIT_MS );
538 fmod_audio_errcheck(
"_sound->getLength()", result);
540 return ((
double)
length) / 1000.0;
555 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
565 set_3d_attributes_on_channel();
571 void FmodAudioSound::
572 set_3d_attributes_on_channel() {
577 result = _sound->getMode(&soundMode);
578 fmod_audio_errcheck(
"_sound->getMode()", result);
580 if ((_channel != 0) && (soundMode & FMOD_3D)) {
581 result = _channel->set3DAttributes( &_location, &_velocity );
582 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
585 fmod_audio_errcheck(
"_channel->set3DAttributes()", result);
595 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
596 audio_error(
"get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
610 result = _sound->set3DMinMaxDistance( dist, _max_dist );
611 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
632 result = _sound->set3DMinMaxDistance( _min_dist, dist );
633 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
670 result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright );
671 fmod_audio_errcheck(
"_channel->getSpeakerMix()", result);
674 case AudioManager::SPK_frontleft:
return frontleft;
675 case AudioManager::SPK_frontright:
return frontright;
676 case AudioManager::SPK_center:
return center;
677 case AudioManager::SPK_sub:
return sub;
678 case AudioManager::SPK_backleft:
return backleft;
679 case AudioManager::SPK_backright:
return backright;
680 case AudioManager::SPK_sideleft:
return sideleft;
681 case AudioManager::SPK_sideright:
return sideright;
695 set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat sideright) {
697 _mix[AudioManager::SPK_frontleft] = frontleft;
698 _mix[AudioManager::SPK_frontright] = frontright;
699 _mix[AudioManager::SPK_center] = center;
700 _mix[AudioManager::SPK_sub] = sub;
701 _mix[AudioManager::SPK_backleft] = backleft;
702 _mix[AudioManager::SPK_backright] = backright;
703 _mix[AudioManager::SPK_sideleft] = sideleft;
704 _mix[AudioManager::SPK_sideright] = sideright;
706 set_speaker_mix_or_balance_on_channel();
717 void FmodAudioSound::
718 set_speaker_mix_or_balance_on_channel() {
723 result = _sound->getMode(&soundMode);
724 fmod_audio_errcheck(
"_sound->getMode()", result);
726 if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
727 if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
728 result = _channel->setPan( _balance );
730 result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft],
731 _mix[AudioManager::SPK_frontright],
732 _mix[AudioManager::SPK_center],
733 _mix[AudioManager::SPK_sub],
734 _mix[AudioManager::SPK_backleft],
735 _mix[AudioManager::SPK_backright],
736 _mix[AudioManager::SPK_sideleft],
737 _mix[AudioManager::SPK_sideright]
740 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
743 fmod_audio_errcheck(
"_channel->setSpeakerMix()/setPan()", result);
754 audio_debug(
"FmodAudioSound::get_priority()");
762 void FmodAudioSound::
763 set_priority(
int priority) {
766 audio_debug(
"FmodAudioSound::set_priority()");
770 _priority = priority;
772 result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
773 fmod_audio_errcheck(
"_sound->setDefaults()", result);
785 if ( _channel == 0 ) {
789 result = _channel->isPlaying( &playingState );
790 if ((result == FMOD_OK) && (playingState ==
true)) {
805 if (_active != active) {
817 if (
status() == PLAYING) {
843 audio_error(
"finished: not implemented under FMOD-EX");
853 audio_error(
"set_finished_event: not implemented under FMOD-EX");
864 audio_error(
"get_finished_event: not implemented under FMOD-EX");
865 return _finished_event;
872 FMOD_RESULT F_CALLBACK FmodAudioSound::
873 sound_end_callback(FMOD_CHANNEL * channel,
874 FMOD_CHANNEL_CALLBACKTYPE type,
876 void *commanddata2) {
880 if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
881 FMOD::Channel *fc = (FMOD::Channel *)channel;
882 void *userdata =
nullptr;
883 FMOD_RESULT result = fc->getUserData(&userdata);
884 fmod_audio_errcheck(
"channel->getUserData()", result);
886 fsound->_self_ref = fsound;
894 FMOD_RESULT F_CALLBACK FmodAudioSound::
895 open_callback(
const char *name,
int,
unsigned int *file_size,
896 void **handle,
void **user_data) {
899 if (file ==
nullptr) {
900 return FMOD_ERR_FILE_NOTFOUND;
902 if (fmodAudio_cat.is_spam()) {
904 <<
"open_callback(" << *file <<
")\n";
910 (*handle) = (
void *)str;
911 (*user_data) = (
void *)file;
923 FMOD_RESULT F_CALLBACK FmodAudioSound::
924 close_callback(
void *handle,
void *user_data) {
926 if (fmodAudio_cat.is_spam()) {
928 <<
"close_callback(" << *file <<
")\n";
933 istream *str = (istream *)handle;
945 FMOD_RESULT F_CALLBACK FmodAudioSound::
946 read_callback(
void *handle,
void *buffer,
unsigned int size_bytes,
947 unsigned int *bytes_read,
void *user_data) {
949 if (fmodAudio_cat.is_spam()) {
951 <<
"read_callback(" << *file <<
", " << size_bytes <<
")\n";
954 istream *str = (istream *)handle;
955 str->read((
char *)buffer, size_bytes);
956 (*bytes_read) = str->gcount();
964 if ((*bytes_read) == 0) {
965 return FMOD_ERR_FILE_EOF;
971 return FMOD_ERR_FILE_BAD;
980 FMOD_RESULT F_CALLBACK FmodAudioSound::
981 seek_callback(
void *handle,
unsigned int pos,
void *user_data) {
983 if (fmodAudio_cat.is_spam()) {
985 <<
"seek_callback(" << *file <<
", " << pos <<
")\n";
988 istream *str = (istream *)handle;
992 if (str->fail() && !str->eof()) {
993 return FMOD_ERR_FILE_COULDNOTSEEK;
AudioSound::SoundStatus status() const
Get status of the sound.
virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat sideright)
This sets the speaker mix for Surround Sound sytems.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PN_stdfloat get_balance() const
-1.0 to 1.0 scale -1 should be all the way left.
void play()
Plays a sound.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PN_stdfloat get_3d_min_distance() const
Get the distance that this sound begins to fall off.
void finished()
Not implemented.
A hierarchy of directories and files that appears to be one continuous file system,...
void set_3d_max_distance(PN_stdfloat dist)
Set the distance that this sound stops falling off.
virtual std::streamsize get_file_size(std::istream *stream) const
Returns the current size on disk (or wherever it is) of the already-open file.
void set_binary()
Indicates that the filename represents a binary file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_volume(PN_stdfloat volume=1.0)
0.0 to 1.0 scale of volume converted to Fmod's internal 0.0 to 255.0 scale.
PN_stdfloat length() const
Get length FMOD returns the time in MS so we have to convert to seconds.
const std::string & get_name() const
Get name of sound file.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
bool get_active() const
Returns whether the sound has been marked "active".
void set_balance(PN_stdfloat balance_right=0.0)
-1.0 to 1.0 scale
void set_loop_count(unsigned long loop_count=1)
Panda uses 0 to mean loop forever.
void set_time(PN_stdfloat start_time=0.0)
Sets the time at which the next play() operation will begin.
The abstract base class for a file or directory within the VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PN_stdfloat get_3d_max_distance() const
Get the distance that this sound stops falling off.
virtual bool get_system_info(SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_loop(bool loop=true)
Turns looping on and off.
void set_3d_min_distance(PN_stdfloat dist)
Set the distance that this sound begins to fall off.
void set_play_rate(PN_stdfloat play_rate=1.0f)
Sets the speed at which a sound plays back.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
FmodAudioSound(AudioManager *manager, VirtualFile *file, bool positional)
Constructor All sound will DEFAULT load as a 2D sound unless otherwise specified.
unsigned long get_loop_count() const
Return how many times a sound will loop.
std::string read_file(bool auto_unwrap) const
Returns the entire contents of the file as a string.
const Filename & get_original_filename() const
Returns the original filename as it was used to locate this VirtualFile.
Similar to MutexHolder, but for a reentrant mutex.
void set_active(bool active=true)
Sets whether the sound is marked "active".
void ref() const
Explicitly increments the reference count.
std::string get_extension() const
Returns the file extension.
bool get_loop() const
Returns whether looping is on or off.
PN_stdfloat get_time() const
Gets the play position within the sound.
virtual std::istream * open_read_file(bool auto_unwrap) const
Opens the file for reading.
const std::string & get_finished_event() const
NOT USED ANYMORE!!! Return the string the finished event is referenced by.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class records a particular byte sub-range within an existing file on disk.
void set_finished_event(const std::string &event)
NOT USED ANYMORE!!! Assign a string for the finished event to be referenced by in python by an accept...
void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz)
Set position and velocity of this sound NOW LISTEN UP!!! THIS IS IMPORTANT! Both Panda3D and FMOD use...
void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz)
Get position and velocity of this sound Currently unimplemented.
~FmodAudioSound()
DESTRUCTOR!!!
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
virtual PN_stdfloat get_speaker_mix(int speaker)
In Multichannel Speaker systems [like Surround].
PN_stdfloat get_volume() const
Gets the current volume of a sound.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.