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, even though the files may originate from several different sources that may not be related to the actual OS's 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.