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
127 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
130 result = FMOD_ERR_FILE_BAD;
137 os_filename = info.get_filename().to_os_specific();
138 name_or_data = os_filename.c_str();
139 sound_info.fileoffset = (
unsigned int)info.get_start();
140 sound_info.length = (
unsigned int)info.get_size();
141 flags |= FMOD_CREATESTREAM;
142 if (fmodAudio_cat.is_debug()) {
143 fmodAudio_cat.debug()
144 <<
"Streaming " << _file_name <<
" from disk (" << name_or_data
145 <<
", " << sound_info.fileoffset <<
", " << sound_info.length <<
")\n";
149 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
154 if (result == FMOD_ERR_FILE_BAD) {
155 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
158 name_or_data = (
const char *)file;
159 sound_info.fileoffset = 0;
160 sound_info.length = (
unsigned int)info.get_size();
161 sound_info.useropen = open_callback;
162 sound_info.userclose = close_callback;
163 sound_info.userread = read_callback;
164 sound_info.userseek = seek_callback;
165 flags |= FMOD_CREATESTREAM;
166 if (fmodAudio_cat.is_debug()) {
167 fmodAudio_cat.debug()
168 <<
"Streaming " << _file_name <<
" from disk using callbacks\n";
171 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
177 fmodAudio_cat.warning()
178 <<
"Cannot stream " << _file_name <<
"; file is not literally on disk.\n";
184 if (result != FMOD_OK) {
185 audio_error(
"createSound(" << _file_name <<
"): " << FMOD_ErrorString(result));
188 FMOD_CREATESOUNDEXINFO sound_info;
189 memset(&sound_info, 0,
sizeof(sound_info));
190 char blank_data[100];
191 memset(blank_data, 0,
sizeof(blank_data));
192 sound_info.cbsize =
sizeof(sound_info);
193 sound_info.length =
sizeof(blank_data);
194 sound_info.numchannels = 1;
195 sound_info.defaultfrequency = 8000;
196 sound_info.format = FMOD_SOUND_FORMAT_PCM16;
197 int flags = FMOD_SOFTWARE | FMOD_OPENMEMORY | FMOD_OPENRAW;
199 result = _manager->_system->createSound( blank_data, flags, &sound_info, &_sound);
200 fmod_audio_errcheck(
"createSound (blank)", result);
205 _sound->setLoopCount(1);
206 _sound->setMode(FMOD_LOOP_OFF);
213 result = _sound->getDefaults( &_sampleFrequency, &_volume , &_balance, &_priority);
214 fmod_audio_errcheck(
"_sound->getDefaults()", result);
227 _manager->_all_sounds.erase(
this);
230 result = _sound->release();
231 fmod_audio_errcheck(
"_sound->release()", result);
252 result =_channel->stop();
253 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
255 }
else if (result == FMOD_OK) {
258 fmod_audio_errcheck(
"_channel->stop()", result);
298 audio_debug(
"FmodAudioSound::set_loop_count() Setting the sound's loop count to: " << loop_count);
303 if (loop_count == 0) {
304 result = _sound->setLoopCount( -1 );
305 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
306 result =_sound->setMode(FMOD_LOOP_NORMAL);
307 fmod_audio_errcheck(
"_sound->setMode()", result);
308 }
else if (loop_count == 1) {
309 result = _sound->setLoopCount( 1 );
310 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
311 result =_sound->setMode(FMOD_LOOP_OFF);
312 fmod_audio_errcheck(
"_sound->setMode()", result);
314 result = _sound->setLoopCount( loop_count );
315 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
316 result =_sound->setMode(FMOD_LOOP_NORMAL);
317 fmod_audio_errcheck(
"_sound->setMode()", result);
320 audio_debug(
"FmodAudioSound::set_loop_count() Sound's loop count should be set to: " << loop_count);
332 result = _sound->getLoopCount( &loop_count );
333 fmod_audio_errcheck(
"_sound->getLoopCount()", result);
335 if (loop_count <= 0) {
338 return (
unsigned long)loop_count;
349 _start_time = start_time;
351 if (
status() == PLAYING) {
364 unsigned int current_time;
370 result = _channel->getPosition( ¤t_time , FMOD_TIMEUNIT_MS );
371 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
374 fmod_audio_errcheck(
"_channel->getPosition()", result);
376 return ((
double)current_time) / 1000.0;
386 set_volume_on_channel();
410 int startTime = (int)(_start_time * 1000);
414 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
415 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
419 fmod_audio_errcheck(
"_channel->setPosition()", result);
422 result = _channel->isPlaying(&playing);
423 fmod_audio_errcheck(
"_channel->isPlaying()", result);
424 if (result != FMOD_OK || !playing) {
431 result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound,
true, &_channel);
432 fmod_audio_errcheck(
"_system->playSound()", result);
433 result = _channel->setChannelGroup(_manager->_channelgroup);
434 fmod_audio_errcheck(
"_channel->setChannelGroup()", result);
435 result = _channel->setUserData(
this);
436 fmod_audio_errcheck(
"_channel->setUserData()", result);
437 result = _channel->setCallback(sound_end_callback);
438 fmod_audio_errcheck(
"_channel->setCallback()", result);
439 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
440 fmod_audio_errcheck(
"_channel->setPosition()", result);
442 set_volume_on_channel();
443 set_play_rate_on_channel();
444 set_speaker_mix_or_balance_on_channel();
446 set_3d_attributes_on_channel();
448 result = _channel->setPaused(
false);
449 fmod_audio_errcheck(
"_channel->setPaused()", result);
459set_volume_on_channel() {
464 result = _channel->setVolume( _volume );
465 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
468 fmod_audio_errcheck(
"_channel->setVolume()", result);
480 set_speaker_mix_or_balance_on_channel();
503 set_play_rate_on_channel();
509PN_stdfloat FmodAudioSound::
510get_play_rate()
const {
518set_play_rate_on_channel() {
521 PN_stdfloat frequency = _sampleFrequency * _playrate;
524 result = _channel->setFrequency( frequency );
525 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
528 fmod_audio_errcheck(
"_channel->setFrequency()", result);
550 result = _sound->getLength( &
length, FMOD_TIMEUNIT_MS );
551 fmod_audio_errcheck(
"_sound->getLength()", result);
553 return ((
double)
length) / 1000.0;
568set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
578 set_3d_attributes_on_channel();
585set_3d_attributes_on_channel() {
590 result = _sound->getMode(&soundMode);
591 fmod_audio_errcheck(
"_sound->getMode()", result);
593 if ((_channel != 0) && (soundMode & FMOD_3D)) {
594 result = _channel->set3DAttributes( &_location, &_velocity );
595 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
598 fmod_audio_errcheck(
"_channel->set3DAttributes()", result);
608get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
609 audio_error(
"get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
623 result = _sound->set3DMinMaxDistance( dist, _max_dist );
624 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
645 result = _sound->set3DMinMaxDistance( _min_dist, dist );
646 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
683 result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright );
684 fmod_audio_errcheck(
"_channel->getSpeakerMix()", result);
687 case AudioManager::SPK_frontleft:
return frontleft;
688 case AudioManager::SPK_frontright:
return frontright;
689 case AudioManager::SPK_center:
return center;
690 case AudioManager::SPK_sub:
return sub;
691 case AudioManager::SPK_backleft:
return backleft;
692 case AudioManager::SPK_backright:
return backright;
693 case AudioManager::SPK_sideleft:
return sideleft;
694 case AudioManager::SPK_sideright:
return sideright;
708set_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) {
710 _mix[AudioManager::SPK_frontleft] = frontleft;
711 _mix[AudioManager::SPK_frontright] = frontright;
712 _mix[AudioManager::SPK_center] = center;
713 _mix[AudioManager::SPK_sub] = sub;
714 _mix[AudioManager::SPK_backleft] = backleft;
715 _mix[AudioManager::SPK_backright] = backright;
716 _mix[AudioManager::SPK_sideleft] = sideleft;
717 _mix[AudioManager::SPK_sideright] = sideright;
719 set_speaker_mix_or_balance_on_channel();
731set_speaker_mix_or_balance_on_channel() {
736 result = _sound->getMode(&soundMode);
737 fmod_audio_errcheck(
"_sound->getMode()", result);
739 if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
740 if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
741 result = _channel->setPan( _balance );
743 result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft],
744 _mix[AudioManager::SPK_frontright],
745 _mix[AudioManager::SPK_center],
746 _mix[AudioManager::SPK_sub],
747 _mix[AudioManager::SPK_backleft],
748 _mix[AudioManager::SPK_backright],
749 _mix[AudioManager::SPK_sideleft],
750 _mix[AudioManager::SPK_sideright]
753 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
756 fmod_audio_errcheck(
"_channel->setSpeakerMix()/setPan()", result);
767 audio_debug(
"FmodAudioSound::get_priority()");
776set_priority(
int priority) {
779 audio_debug(
"FmodAudioSound::set_priority()");
783 _priority = priority;
785 result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
786 fmod_audio_errcheck(
"_sound->setDefaults()", result);
798 if ( _channel == 0 ) {
802 result = _channel->isPlaying( &playingState );
803 if ((result == FMOD_OK) && (playingState ==
true)) {
818 if (_active != active) {
830 if (
status() == PLAYING) {
857 audio_error(
"finished: not implemented under FMOD-EX");
867 audio_error(
"set_finished_event: not implemented under FMOD-EX");
878 audio_error(
"get_finished_event: not implemented under FMOD-EX");
879 return _finished_event;
886FMOD_RESULT F_CALLBACK FmodAudioSound::
887sound_end_callback(FMOD_CHANNEL * channel,
888 FMOD_CHANNEL_CALLBACKTYPE type,
890 void *commanddata2) {
894 if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
895 FMOD::Channel *fc = (FMOD::Channel *)channel;
896 void *userdata =
nullptr;
897 FMOD_RESULT result = fc->getUserData(&userdata);
898 fmod_audio_errcheck(
"channel->getUserData()", result);
900 fsound->_self_ref = fsound;
908FMOD_RESULT F_CALLBACK FmodAudioSound::
909open_callback(
const char *name,
int,
unsigned int *file_size,
910 void **handle,
void **user_data) {
913 if (file ==
nullptr) {
914 return FMOD_ERR_FILE_NOTFOUND;
916 if (fmodAudio_cat.is_spam()) {
918 <<
"open_callback(" << *file <<
")\n";
924 (*handle) = (
void *)str;
925 (*user_data) = (
void *)file;
937FMOD_RESULT F_CALLBACK FmodAudioSound::
938close_callback(
void *handle,
void *user_data) {
940 if (fmodAudio_cat.is_spam()) {
942 <<
"close_callback(" << *file <<
")\n";
947 istream *str = (istream *)handle;
959FMOD_RESULT F_CALLBACK FmodAudioSound::
960read_callback(
void *handle,
void *buffer,
unsigned int size_bytes,
961 unsigned int *bytes_read,
void *user_data) {
963 if (fmodAudio_cat.is_spam()) {
965 <<
"read_callback(" << *file <<
", " << size_bytes <<
")\n";
968 istream *str = (istream *)handle;
969 str->read((
char *)buffer, size_bytes);
970 (*bytes_read) = str->gcount();
978 if ((*bytes_read) == 0) {
979 return FMOD_ERR_FILE_EOF;
985 return FMOD_ERR_FILE_BAD;
994FMOD_RESULT F_CALLBACK FmodAudioSound::
995seek_callback(
void *handle,
unsigned int pos,
void *user_data) {
997 if (fmodAudio_cat.is_spam()) {
999 <<
"seek_callback(" << *file <<
", " << pos <<
")\n";
1002 istream *str = (istream *)handle;
1006 if (str->fail() && !str->eof()) {
1007 return FMOD_ERR_FILE_COULDNOTSEEK;
void set_binary()
Indicates that the filename represents a binary file.
std::string get_extension() const
Returns the file extension.
void set_active(bool active=true)
Sets whether the sound is marked "active".
PN_stdfloat get_3d_max_distance() const
Get the distance that this sound stops falling off.
void set_3d_min_distance(PN_stdfloat dist)
Set the distance that this sound begins to fall off.
void set_time(PN_stdfloat start_time=0.0)
Sets the time at which the next play() operation will begin.
void set_3d_max_distance(PN_stdfloat dist)
Set the distance that this sound stops falling off.
PN_stdfloat get_balance() const
-1.0 to 1.0 scale -1 should be all the way left.
PN_stdfloat get_time() const
Gets the play position within the sound.
void set_loop(bool loop=true)
Turns looping on and off.
void finished()
Not implemented.
PN_stdfloat length() const
Get length FMOD returns the time in MS so we have to convert to seconds.
void set_loop_count(unsigned long loop_count=1)
Panda uses 0 to mean loop forever.
virtual PN_stdfloat get_speaker_mix(int speaker)
In Multichannel Speaker systems [like Surround].
AudioSound::SoundStatus status() const
Get status of the sound.
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.
PN_stdfloat get_3d_min_distance() const
Get the distance that this sound begins to fall off.
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.
const std::string & get_name() const
Get name of sound file.
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.
const std::string & get_finished_event() const
NOT USED ANYMORE!!! Return the string the finished event is referenced by.
PN_stdfloat get_volume() const
Gets the current volume of a sound.
void play()
Plays a sound.
~FmodAudioSound()
DESTRUCTOR!!!
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...
unsigned long get_loop_count() const
Return how many times a sound will loop.
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...
bool get_active() const
Returns whether the sound has been marked "active".
FmodAudioSound(AudioManager *manager, VirtualFile *file, bool positional)
Constructor All sound will DEFAULT load as a 2D sound unless otherwise specified.
void set_balance(PN_stdfloat balance_right=0.0)
-1.0 to 1.0 scale
void set_play_rate(PN_stdfloat play_rate=1.0f)
Sets the speed at which a sound plays back.
bool get_loop() const
Returns whether looping is on or off.
Similar to MutexHolder, but for a reentrant mutex.
void ref() const
Explicitly increments the reference count.
This class records a particular byte sub-range within an existing file on disk.
TypeHandle is the identifier used to differentiate C++ class types.
A hierarchy of directories and files that appears to be one continuous file system,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
The abstract base class for a file or directory within the VirtualFileSystem.
virtual std::istream * open_read_file(bool auto_unwrap) const
Opens the file for reading.
virtual bool get_system_info(SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
const Filename & get_original_filename() const
Returns the original filename as it was used to locate this VirtualFile.
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.
std::string read_file(bool auto_unwrap) const
Returns the entire contents of the file as a string.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.