1 /** 2 * @file 3 * 4 * Audiere Sound System 5 * Version 1.9.4 6 * (c) 2001-2003 Chad Austin 7 * 8 * This API uses principles explained at 9 * http://aegisknight.org/cppinterface.html 10 * 11 * This code licensed under the terms of the LGPL. See doc/license.txt. 12 * 13 * 14 * Note: When compiling this header in gcc, you may want to use the 15 * -Wno-non-virtual-dtor flag to get rid of those annoying "class has 16 * virtual functions but no virtual destructor" warnings. 17 * 18 * This file is structured as follows: 19 * - includes, macro definitions, other general setup 20 * - interface definitions 21 * - DLL-safe entry points (not for general use) 22 * - inline functions that use those entry points 23 */ 24 25 #ifndef AUDIERE_H 26 #define AUDIERE_H 27 28 29 #include <vector> 30 #include <string> 31 #include <cstring> // strlen memcpy etc 32 #include <cstdio> // for sprintf 33 34 #ifdef _MSC_VER 35 #pragma warning(disable : 4786) 36 #endif 37 38 39 #ifndef __cplusplus 40 #error Audiere requires C++ 41 #endif 42 43 44 // DLLs in Windows should use the standard (Pascal) calling convention 45 #ifndef ADR_CALL 46 #if defined(WIN32) || defined(_WIN32) 47 #define ADR_CALL __stdcall 48 #else 49 #define ADR_CALL 50 #endif 51 #endif 52 53 // Export functions from the DLL 54 #ifndef ADR_DECL 55 # if defined(WIN32) || defined(_WIN32) 56 # ifdef AUDIERE_EXPORTS 57 # define ADR_DECL __declspec(dllexport) 58 # else 59 # define ADR_DECL __declspec(dllimport) 60 # endif 61 # else 62 # define ADR_DECL 63 # endif 64 #endif 65 66 67 68 #define ADR_FUNCTION(ret) extern "C" ADR_DECL ret ADR_CALL 69 #define ADR_METHOD(ret) virtual ret ADR_CALL 70 71 72 namespace audiere { 73 74 class RefCounted { 75 protected: 76 /** 77 * Protected so users of refcounted classes don't use std::auto_ptr 78 * or the delete operator. 79 * 80 * Interfaces that derive from RefCounted should define an inline, 81 * empty, protected destructor as well. 82 */ ~RefCounted()83 ~RefCounted() { } 84 85 public: 86 /** 87 * Add a reference to the internal reference count. 88 */ 89 ADR_METHOD(void) ref() = 0; 90 91 /** 92 * Remove a reference from the internal reference count. When this 93 * reaches 0, the object is destroyed. 94 */ 95 ADR_METHOD(void) unref() = 0; 96 }; 97 98 99 template<typename T> 100 class RefPtr { 101 public: 102 RefPtr(T* ptr = 0) { 103 m_ptr = 0; 104 *this = ptr; 105 } 106 RefPtr(const RefPtr<T> & ptr)107 RefPtr(const RefPtr<T>& ptr) { 108 m_ptr = 0; 109 *this = ptr; 110 } 111 ~RefPtr()112 ~RefPtr() { 113 if (m_ptr) { 114 m_ptr->unref(); 115 m_ptr = 0; 116 } 117 } 118 119 RefPtr<T>& operator=(T* ptr) { 120 if (ptr != m_ptr) { 121 if (m_ptr) { 122 m_ptr->unref(); 123 } 124 m_ptr = ptr; 125 if (m_ptr) { 126 m_ptr->ref(); 127 } 128 } 129 return *this; 130 } 131 132 RefPtr<T>& operator=(const RefPtr<T>& ptr) { 133 *this = ptr.m_ptr; 134 return *this; 135 } 136 137 T* operator->() const { 138 return m_ptr; 139 } 140 141 T& operator*() const { 142 return *m_ptr; 143 } 144 145 operator bool() const { 146 return (m_ptr != 0); 147 } 148 get()149 T* get() const { 150 return m_ptr; 151 } 152 153 private: 154 T* m_ptr; 155 }; 156 157 158 template<typename T, typename U> 159 bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) { 160 return (a.get() == b.get()); 161 } 162 163 template<typename T> 164 bool operator==(const RefPtr<T>& a, const T* b) { 165 return (a.get() == b); 166 } 167 168 template<typename T> 169 bool operator==(const T* a, const RefPtr<T>& b) { 170 return (a == b.get()); 171 } 172 173 174 template<typename T, typename U> 175 bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) { 176 return (a.get() != b.get()); 177 } 178 179 template<typename T> 180 bool operator!=(const RefPtr<T>& a, const T* b) { 181 return (a.get() != b); 182 } 183 184 template<typename T> 185 bool operator!=(const T* a, const RefPtr<T>& b) { 186 return (a != b.get()); 187 } 188 189 190 /** 191 * A basic implementation of the RefCounted interface. Derive 192 * your implementations from RefImplementation<YourInterface>. 193 */ 194 template<class Interface> 195 class RefImplementation : public Interface { 196 protected: RefImplementation()197 RefImplementation() { 198 m_ref_count = 0; 199 } 200 201 /** 202 * So the implementation can put its destruction logic in the destructor, 203 * as natural C++ code does. 204 */ ~RefImplementation()205 virtual ~RefImplementation() { } 206 207 public: ref()208 void ADR_CALL ref() { 209 ++m_ref_count; 210 } 211 unref()212 void ADR_CALL unref() { 213 if (--m_ref_count == 0) { 214 delete this; 215 } 216 } 217 218 private: 219 int m_ref_count; 220 }; 221 222 223 /** 224 * Represents a random-access file, usually stored on a disk. Files 225 * are always binary: that is, they do no end-of-line 226 * transformations. File objects are roughly analogous to ANSI C 227 * FILE* objects. 228 * 229 * This interface is not synchronized. 230 */ 231 class File : public RefCounted { 232 protected: ~File()233 ~File() { } 234 235 public: 236 /** 237 * The different ways you can seek within a file. 238 */ 239 enum SeekMode { 240 BEGIN, 241 CURRENT, 242 END, 243 }; 244 245 /** 246 * Read size bytes from the file, storing them in buffer. 247 * 248 * @param buffer buffer to read into 249 * @param size number of bytes to read 250 * 251 * @return number of bytes successfully read 252 */ 253 ADR_METHOD(int) read(void* buffer, int size) = 0; 254 255 /** 256 * Jump to a new position in the file, using the specified seek 257 * mode. Remember: if mode is END, the position must be negative, 258 * to seek backwards from the end of the file into its contents. 259 * If the seek fails, the current position is undefined. 260 * 261 * @param position position relative to the mode 262 * @param mode where to seek from in the file 263 * 264 * @return true on success, false otherwise 265 */ 266 ADR_METHOD(bool) seek(int position, SeekMode mode) = 0; 267 268 /** 269 * Get current position within the file. 270 * 271 * @return current position 272 */ 273 ADR_METHOD(int) tell() = 0; 274 }; 275 typedef RefPtr<File> FilePtr; 276 277 278 /// Storage formats for sample data. 279 enum SampleFormat { 280 SF_U8, ///< unsigned 8-bit integer [0,255] 281 SF_S16, ///< signed 16-bit integer in host endianness [-32768,32767] 282 }; 283 284 285 /// Supported audio file formats. 286 enum FileFormat { 287 FF_AUTODETECT, 288 FF_WAV, 289 FF_OGG, 290 FF_FLAC, 291 FF_MP3, 292 FF_MOD, 293 FF_AIFF, 294 FF_SPEEX, 295 }; 296 297 298 /** 299 * Source of raw PCM samples. Sample sources have an intrinsic format 300 * (@see SampleFormat), sample rate, and number of channels. They can 301 * be read from or reset. 302 * 303 * Some sample sources are seekable. Seekable sources have two additional 304 * properties: length and position. Length is read-only. 305 * 306 * This interface is not synchronized. 307 */ 308 class SampleSource : public RefCounted { 309 protected: ~SampleSource()310 ~SampleSource() { } 311 312 public: 313 /** 314 * Retrieve the number of channels, sample rate, and sample format of 315 * the sample source. 316 */ 317 ADR_METHOD(void) getFormat( 318 int& channel_count, 319 int& sample_rate, 320 SampleFormat& sample_format) = 0; 321 322 /** 323 * Read frame_count samples into buffer. buffer must be at least 324 * |frame_count * GetSampleSize(format) * channel_count| bytes long. 325 * 326 * @param frame_count number of frames to read 327 * @param buffer buffer to store samples in 328 * 329 * @return number of frames actually read 330 */ 331 ADR_METHOD(int) read(int frame_count, void* buffer) = 0; 332 333 /** 334 * Reset the sample source. This has the same effect as setPosition(0) 335 * on a seekable source. On an unseekable source, it resets all internal 336 * state to the way it was when the source was first created. 337 */ 338 ADR_METHOD(void) reset() = 0; 339 340 /** 341 * @return true if the stream is seekable, false otherwise 342 */ 343 ADR_METHOD(bool) isSeekable() = 0; 344 345 /** 346 * @return number of frames in the stream, or 0 if the stream is not 347 * seekable 348 */ 349 ADR_METHOD(int) getLength() = 0; 350 351 /** 352 * Sets the current position within the sample source. If the stream 353 * is not seekable, this method does nothing. 354 * 355 * @param position current position in frames 356 */ 357 ADR_METHOD(void) setPosition(int position) = 0; 358 359 /** 360 * Returns the current position within the sample source. 361 * 362 * @return current position in frames 363 */ 364 ADR_METHOD(int) getPosition() = 0; 365 366 /** 367 * @return true if the sample source is set to repeat 368 */ 369 ADR_METHOD(bool) getRepeat() = 0; 370 371 /** 372 * Sets whether the sample source should repeat or not. Note that not 373 * all sample sources repeat by starting again at the beginning of the 374 * sound. For example MOD files can contain embedded loop points. 375 * 376 * @param repeat true if the source should repeat, false otherwise 377 */ 378 ADR_METHOD(void) setRepeat(bool repeat) = 0; 379 380 /// Returns number of metadata tags present in this sample source. 381 ADR_METHOD(int) getTagCount() = 0; 382 383 /** 384 * Returns the key of the i'th tag in the source. If the tag is 385 * "author=me", the key is "author". 386 */ 387 virtual const char* ADR_CALL getTagKey(int i) = 0; 388 389 /** 390 * Returns the value of the i'th tag in the source. If the tag is 391 * "author=me", the value is "me". 392 */ 393 virtual const char* ADR_CALL getTagValue(int i) = 0; 394 395 /** 396 * Returns the type of the i'th tag in the source. The type is where 397 * the tag comes from, i.e. "ID3v1", "ID3v2", or "vorbis". 398 */ 399 virtual const char* ADR_CALL getTagType(int i) = 0; 400 }; 401 typedef RefPtr<SampleSource> SampleSourcePtr; 402 403 404 /** 405 * LoopPointSource is a wrapper around another SampleSource, providing 406 * custom loop behavior. LoopPointSource maintains a set of links 407 * within the sample stream and whenever the location of one of the links 408 * (i.e. a loop point) is reached, the stream jumps to that link's target. 409 * Each loop point maintains a count. Every time a loop point comes into 410 * effect, the count is decremented. Once it reaches zero, that loop point 411 * is temporarily disabled. If a count is not a positive value, it 412 * cannot be disabled. Calling reset() resets all counts to their initial 413 * values. 414 * 415 * Loop points only take effect when repeating has been enabled via the 416 * setRepeat() method. 417 * 418 * Loop points are stored in sorted order by their location. Each one 419 * has an index based on its location within the list. A loop point's 420 * index will change if another is added before it. 421 * 422 * There is always one implicit loop point after the last sample that 423 * points back to the first. That way, this class's default looping 424 * behavior is the same as a standard SampleSource. This loop point 425 * does not show up in the list. 426 */ 427 class LoopPointSource : public SampleSource { 428 protected: ~LoopPointSource()429 ~LoopPointSource() { } 430 431 public: 432 /** 433 * Adds a loop point to the stream. If a loop point at 'location' 434 * already exists, the new one replaces it. Location and target are 435 * clamped to the actual length of the stream. 436 * 437 * @param location frame where loop occurs 438 * @param target frame to jump to after loop point is hit 439 * @param loopCount number of times to execute this jump. 440 */ 441 ADR_METHOD(void) addLoopPoint( 442 int location, int target, int loopCount) = 0; 443 444 /** 445 * Removes the loop point at index 'index' from the stream. 446 * 447 * @param index index of the loop point to remove 448 */ 449 ADR_METHOD(void) removeLoopPoint(int index) = 0; 450 451 /** 452 * Returns the number of loop points in this stream. 453 */ 454 ADR_METHOD(int) getLoopPointCount() = 0; 455 456 /** 457 * Retrieves information about a specific loop point. 458 * 459 * @param index index of the loop point 460 * @param location frame where loop occurs 461 * @param target loop point's target frame 462 * @param loopCount number of times to loop from this particular point 463 * 464 * @return true if the index is valid and information is returned 465 */ 466 ADR_METHOD(bool) getLoopPoint( 467 int index, int& location, int& target, int& loopCount) = 0; 468 }; 469 typedef RefPtr<LoopPointSource> LoopPointSourcePtr; 470 471 472 /** 473 * A connection to an audio device. Multiple output streams are 474 * mixed by the audio device to produce the final waveform that the 475 * user hears. 476 * 477 * Each output stream can be independently played and stopped. They 478 * also each have a volume from 0.0 (silence) to 1.0 (maximum volume). 479 */ 480 class OutputStream : public RefCounted { 481 protected: ~OutputStream()482 ~OutputStream() { } 483 484 public: 485 /** 486 * Start playback of the output stream. If the stream is already 487 * playing, this does nothing. 488 */ 489 ADR_METHOD(void) play() = 0; 490 491 /** 492 * Stop playback of the output stream. If the stream is already 493 * stopped, this does nothing. 494 */ 495 ADR_METHOD(void) stop() = 0; 496 497 /** 498 * @return true if the output stream is playing, false otherwise 499 */ 500 ADR_METHOD(bool) isPlaying() = 0; 501 502 /** 503 * Reset the sample source or buffer to the beginning. On seekable 504 * streams, this operation is equivalent to setPosition(0). 505 * 506 * On some output streams, this operation can be moderately slow, as up to 507 * several seconds of PCM buffer must be refilled. 508 */ 509 ADR_METHOD(void) reset() = 0; 510 511 /** 512 * Set whether the output stream should repeat. 513 * 514 * @param repeat true if the stream should repeat, false otherwise 515 */ 516 ADR_METHOD(void) setRepeat(bool repeat) = 0; 517 518 /** 519 * @return true if the stream is repeating 520 */ 521 ADR_METHOD(bool) getRepeat() = 0; 522 523 /** 524 * Sets the stream's volume. 525 * 526 * @param volume 0.0 = silence, 1.0 = maximum volume (default) 527 */ 528 ADR_METHOD(void) setVolume(float volume) = 0; 529 530 /** 531 * Gets the current volume. 532 * 533 * @return current volume of the output stream 534 */ 535 ADR_METHOD(float) getVolume() = 0; 536 537 /** 538 * Set current pan. 539 * 540 * @param pan -1.0 = left, 0.0 = center (default), 1.0 = right 541 */ 542 ADR_METHOD(void) setPan(float pan) = 0; 543 544 /** 545 * Get current pan. 546 */ 547 ADR_METHOD(float) getPan() = 0; 548 549 /** 550 * Set current pitch shift. 551 * 552 * @param shift can range from 0.5 to 2.0. default is 1.0. 553 */ 554 ADR_METHOD(void) setPitchShift(float shift) = 0; 555 556 /** 557 * Get current pitch shift. Defaults to 1.0. 558 */ 559 ADR_METHOD(float) getPitchShift() = 0; 560 561 /** 562 * @return true if the stream is seekable, false otherwise 563 */ 564 ADR_METHOD(bool) isSeekable() = 0; 565 566 /** 567 * @return number of frames in the stream, or 0 if the stream is not 568 * seekable 569 */ 570 ADR_METHOD(int) getLength() = 0; 571 572 /** 573 * Sets the current position within the sample source. If the stream 574 * is not seekable, this method does nothing. 575 * 576 * @param position current position in frames 577 */ 578 ADR_METHOD(void) setPosition(int position) = 0; 579 580 /** 581 * Returns the current position within the sample source. 582 * 583 * @return current position in frames 584 */ 585 ADR_METHOD(int) getPosition() = 0; 586 }; 587 typedef RefPtr<OutputStream> OutputStreamPtr; 588 589 590 /// An integral code representing a specific type of event. 591 enum EventType { 592 ET_STOP, ///< See StopEvent and StopCallback 593 }; 594 595 596 /// Base interface for event-specific data passed to callbacks. 597 class Event : public RefCounted { 598 protected: ~Event()599 ~Event() { } 600 601 public: 602 /// Returns the EventType code for this event. 603 ADR_METHOD(EventType) getType() = 0; 604 }; 605 typedef RefPtr<Event> EventPtr; 606 607 608 /** 609 * An event object that gets passed to implementations of StopCallback 610 * when a stream has stopped playing. 611 */ 612 class StopEvent : public Event { 613 protected: ~StopEvent()614 ~StopEvent() { } 615 616 public: getType()617 EventType ADR_CALL getType() { return ET_STOP; } 618 619 /// A code representing the reason the stream stopped playback. 620 enum Reason { 621 STOP_CALLED, ///< stop() was called from an external source. 622 STREAM_ENDED, ///< The stream reached its end. 623 }; 624 625 /** 626 * @return Pointer to the OutputStream that stopped playback. 627 */ 628 ADR_METHOD(OutputStream*) getOutputStream() = 0; 629 630 /** 631 * @return Reason for the stop event. 632 */ 633 ADR_METHOD(Reason) getReason() = 0; 634 }; 635 typedef RefPtr<StopEvent> StopEventPtr; 636 637 638 /** 639 * Base interface for all callbacks. See specific callback implementations 640 * for descriptions. 641 */ 642 class Callback : public RefCounted { 643 protected: ~Callback()644 ~Callback() { } 645 646 public: 647 /** 648 * Returns the event type that this callback knows how to handle. 649 */ 650 ADR_METHOD(EventType) getType() = 0; 651 652 /** 653 * Actually executes the callback with event-specific data. This is 654 * only called if event->getType() == this->getType(). 655 */ 656 ADR_METHOD(void) call(Event* event) = 0; 657 }; 658 typedef RefPtr<Callback> CallbackPtr; 659 660 661 /** 662 * To listen for stream stopped events on a device, implement this interface 663 * and call registerStopCallback() on the device, passing your 664 * implementation. streamStopped() will be called whenever a stream on that 665 * device stops playback. 666 * 667 * WARNING: StopCallback is called from another thread. Make sure your 668 * callback is thread-safe. 669 */ 670 class StopCallback : public Callback { 671 protected: ~StopCallback()672 ~StopCallback() { } 673 674 public: getType()675 EventType ADR_CALL getType() { return ET_STOP; } call(Event * event)676 void ADR_CALL call(Event* event) { 677 streamStopped(static_cast<StopEvent*>(event)); 678 } 679 680 /** 681 * Called when a stream has stopped. 682 * 683 * @param event Information pertaining to the event. 684 */ 685 ADR_METHOD(void) streamStopped(StopEvent* event) = 0; 686 }; 687 typedef RefPtr<StopCallback> StopCallbackPtr; 688 689 690 /** 691 * AudioDevice represents a device on the system which is capable 692 * of opening and mixing multiple output streams. In Windows, 693 * DirectSound is such a device. 694 * 695 * This interface is synchronized. update() and openStream() may 696 * be called on different threads. 697 */ 698 class AudioDevice : public RefCounted { 699 protected: ~AudioDevice()700 ~AudioDevice() { } 701 702 public: 703 /** 704 * Tell the device to do any internal state updates. Some devices 705 * update on an internal thread. If that is the case, this method 706 * does nothing. 707 */ 708 ADR_METHOD(void) update() = 0; 709 710 /** 711 * Open an output stream with a given sample source. If the sample 712 * source ever runs out of data, the output stream automatically stops 713 * itself. 714 * 715 * The output stream takes ownership of the sample source, even if 716 * opening the output stream fails (in which case the source is 717 * immediately deleted). 718 * 719 * @param source the source used to feed the output stream with samples 720 * 721 * @return new output stream if successful, 0 if failure 722 */ 723 ADR_METHOD(OutputStream*) openStream(SampleSource* source) = 0; 724 725 /** 726 * Open a single buffer with the specified PCM data. This is sometimes 727 * more efficient than streaming and works on a larger variety of audio 728 * devices. In some implementations, this may download the audio data 729 * to the sound card's memory itself. 730 * 731 * @param samples Buffer containing sample data. openBuffer() does 732 * not take ownership of the memory. The application 733 * is responsible for freeing it. There must be at 734 * least |frame_count * channel_count * 735 * GetSampleSize(sample_format)| bytes in the buffer. 736 * 737 * @param frame_count Number of frames in the buffer. 738 * 739 * @param channel_count Number of audio channels. 1 = mono, 2 = stereo. 740 * 741 * @param sample_rate Number of samples per second. 742 * 743 * @param sample_format Format of samples in buffer. 744 * 745 * @return new output stream if successful, 0 if failure 746 */ 747 ADR_METHOD(OutputStream*) openBuffer( 748 void* samples, 749 int frame_count, 750 int channel_count, 751 int sample_rate, 752 SampleFormat sample_format) = 0; 753 754 /** 755 * Gets the name of the audio device. For example "directsound" or "oss". 756 * 757 * @return name of audio device 758 */ 759 ADR_METHOD(const char*) getName() = 0; 760 761 /** 762 * Registers 'callback' to receive events. Callbacks can be 763 * registered multiple times. 764 */ 765 ADR_METHOD(void) registerCallback(Callback* callback) = 0; 766 767 /** 768 * Unregisters 'callback' once. If it is registered multiple times, 769 * each unregisterStopCallback call unregisters one of the instances. 770 */ 771 ADR_METHOD(void) unregisterCallback(Callback* callback) = 0; 772 773 /// Clears all of the callbacks from the device. 774 ADR_METHOD(void) clearCallbacks() = 0; 775 }; 776 typedef RefPtr<AudioDevice> AudioDevicePtr; 777 778 779 /** 780 * A readonly sample container which can open sample streams as iterators 781 * through the buffer. This is commonly used in cases where a very large 782 * sound effect is loaded once into memory and then streamed several times 783 * to the audio device. This is more efficient memory-wise than loading 784 * the effect multiple times. 785 * 786 * @see CreateSampleBuffer 787 */ 788 class SampleBuffer : public RefCounted { 789 protected: ~SampleBuffer()790 ~SampleBuffer() { } 791 792 public: 793 794 /** 795 * Return the format of the sample data in the sample buffer. 796 * @see SampleSource::getFormat 797 */ 798 ADR_METHOD(void) getFormat( 799 int& channel_count, 800 int& sample_rate, 801 SampleFormat& sample_format) = 0; 802 803 /** 804 * Get the length of the sample buffer in frames. 805 */ 806 ADR_METHOD(int) getLength() = 0; 807 808 /** 809 * Get a readonly pointer to the samples contained within the buffer. The 810 * buffer is |channel_count * frame_count * GetSampleSize(sample_format)| 811 * bytes long. 812 */ 813 virtual const void* ADR_CALL getSamples() = 0; 814 815 /** 816 * Open a seekable sample source using the samples contained in the 817 * buffer. 818 */ 819 ADR_METHOD(SampleSource*) openStream() = 0; 820 }; 821 typedef RefPtr<SampleBuffer> SampleBufferPtr; 822 823 824 /** 825 * Defines the type of SoundEffect objects. @see SoundEffect 826 */ 827 enum SoundEffectType { 828 SINGLE, 829 MULTIPLE, 830 }; 831 832 833 /** 834 * SoundEffect is a convenience class which provides a simple 835 * mechanism for basic sound playback. There are two types of sound 836 * effects: SINGLE and MULTIPLE. SINGLE sound effects only allow 837 * the sound to be played once at a time. MULTIPLE sound effects 838 * always open a new stream to the audio device for each time it is 839 * played (cleaning up or reusing old streams if possible). 840 */ 841 class SoundEffect : public RefCounted { 842 protected: ~SoundEffect()843 ~SoundEffect() { } 844 845 public: 846 /** 847 * Trigger playback of the sound. If the SoundEffect is of type 848 * SINGLE, this plays the sound if it isn't playing yet, and 849 * starts it again if it is. If the SoundEffect is of type 850 * MULTIPLE, play() simply starts playing the sound again. 851 */ 852 ADR_METHOD(void) play() = 0; 853 854 /** 855 * If the sound is of type SINGLE, stop the sound. If it is of 856 * type MULTIPLE, stop all playing instances of the sound. 857 */ 858 ADR_METHOD(void) stop() = 0; 859 860 /** 861 * Sets the sound's volume. 862 * 863 * @param volume 0.0 = silence, 1.0 = maximum volume (default) 864 */ 865 ADR_METHOD(void) setVolume(float volume) = 0; 866 867 /** 868 * Gets the current volume. 869 * 870 * @return current volume of the output stream 871 */ 872 ADR_METHOD(float) getVolume() = 0; 873 874 /** 875 * Set current pan. 876 * 877 * @param pan -1.0 = left, 0.0 = center (default), 1.0 = right 878 */ 879 ADR_METHOD(void) setPan(float pan) = 0; 880 881 /** 882 * Get current pan. 883 */ 884 ADR_METHOD(float) getPan() = 0; 885 886 /** 887 * Set current pitch shift. 888 * 889 * @param shift can range from 0.5 to 2.0. default is 1.0. 890 */ 891 ADR_METHOD(void) setPitchShift(float shift) = 0; 892 893 /** 894 * Get current pitch shift. Defaults to 1.0. 895 */ 896 ADR_METHOD(float) getPitchShift() = 0; 897 }; 898 typedef RefPtr<SoundEffect> SoundEffectPtr; 899 900 901 /** 902 * Represents a device capable of playing CD audio. Internally, this 903 * uses the MCI subsystem in windows and libcdaudio on other platforms. 904 * MCI subsystem: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_command_strings.asp 905 * libcdaudio: http://cdcd.undergrid.net/libcdaudio/ 906 */ 907 class CDDevice : public RefCounted { 908 protected: ~CDDevice()909 virtual ~CDDevice() { } 910 911 public: 912 /** 913 * Returns the name of this CD Device, often just the device name 914 * it was created with. 915 */ 916 virtual const char* ADR_CALL getName() = 0; 917 918 /** 919 * Returns the number of audio tracks on the disc. 920 */ 921 ADR_METHOD(int) getTrackCount() = 0; 922 923 /** 924 * Starts playback of the given track. If another track was 925 * already playing, the previous track is stopped. IMPORTANT: Tracks are 926 * indexed from 0 to getTrackCount() - 1. 927 */ 928 ADR_METHOD(void) play(int track) = 0; 929 930 /** 931 * Stops the playback, if the playback was already stopped, this 932 * does nothing. 933 */ 934 ADR_METHOD(void) stop() = 0; 935 936 /** 937 * pauses playback of the track that is currently playing (if any) 938 * This does nothing if no track is playing 939 */ 940 ADR_METHOD(void) pause() = 0; 941 942 /** 943 * Resumes playback of the track that is currently paused (if any). 944 * This does nothing if no track is paused. 945 */ 946 ADR_METHOD(void) resume() = 0; 947 948 /** 949 * Returns true if the CD is currently playing a sound, this could 950 * be through us, or through some other program. 951 */ 952 ADR_METHOD(bool) isPlaying() = 0; 953 954 /** 955 * Returns true if the drive contains a cd. This might be slow 956 * on some systems, use with care. 957 */ 958 ADR_METHOD(bool) containsCD() = 0; 959 960 /// Returns true if the door is open. 961 ADR_METHOD(bool) isDoorOpen() = 0; 962 963 /// Opens this device's door. 964 ADR_METHOD(void) openDoor() = 0; 965 966 /// Closes this device's door. 967 ADR_METHOD(void) closeDoor() = 0; 968 }; 969 typedef RefPtr<CDDevice> CDDevicePtr; 970 971 972 /** 973 * An opened MIDI song that can be played, stopped, and seeked within. 974 * Uses MCI under Windows and is not supported in other platforms. 975 */ 976 class MIDIStream : public RefCounted { 977 protected: ~MIDIStream()978 virtual ~MIDIStream() { } 979 980 public: 981 /** 982 * Begins playback of the song and does nothing if the song is already 983 * playing. 984 */ 985 ADR_METHOD(void) play() = 0; 986 987 /// Stops playback of the song and seeks to the beginning. 988 ADR_METHOD(void) stop() = 0; 989 990 /** 991 * Stops playback of the song and does not change its current position. 992 * A subsequent play() will resume the song where it left off. 993 */ 994 ADR_METHOD(void) pause() = 0; 995 996 /// Returns true if the song is currently playing, false otherwise. 997 ADR_METHOD(bool) isPlaying() = 0; 998 999 /// Returns the length of the song in milliseconds. 1000 ADR_METHOD(int) getLength() = 0; 1001 1002 /// Returns the current position of the song in milliseconds. 1003 ADR_METHOD(int) getPosition() = 0; 1004 1005 /// Sets the current position of the song. 1006 ADR_METHOD(void) setPosition(int position) = 0; 1007 1008 /// Returns true if this song is set to repeat. 1009 ADR_METHOD(bool) getRepeat() = 0; 1010 1011 /// Sets whether the song should repeat on completion. Defaults to false. 1012 ADR_METHOD(void) setRepeat(bool repeat) = 0; 1013 }; 1014 typedef RefPtr<MIDIStream> MIDIStreamPtr; 1015 1016 1017 /** 1018 * A MIDIDevice must be instantiated in order to open MIDIStreams. 1019 */ 1020 class MIDIDevice : public RefCounted { 1021 protected: ~MIDIDevice()1022 virtual ~MIDIDevice() { } 1023 1024 public: 1025 /** 1026 * Returns the name of the device. 1027 */ 1028 ADR_METHOD(const char*) getName() = 0; 1029 1030 /** 1031 * openStream() creates and returns a new MIDIStream object from the 1032 * file with the specified name, which then can be queried and played. 1033 * This method returns NULL if the stream cannot be opened. 1034 * 1035 * Note: MCI subsystem limitations do not allow loading MIDIStream 1036 * objects from an audiere File implementation. This may be addressed 1037 * in future versions of this API. 1038 */ 1039 ADR_METHOD(MIDIStream*) openStream(const char* filename) = 0; 1040 }; 1041 typedef RefPtr<MIDIDevice> MIDIDevicePtr; 1042 1043 1044 /// PRIVATE API - for internal use only 1045 namespace hidden { 1046 1047 // these are extern "C" so we don't mangle the names 1048 1049 ADR_FUNCTION(const char*) AdrGetVersion(); 1050 1051 /** 1052 * Returns a formatted string that lists the file formats that Audiere 1053 * supports. This function is DLL-safe. 1054 * 1055 * It is formatted in the following way: 1056 * 1057 * description1:ext1,ext2,ext3;description2:ext1,ext2,ext3 1058 */ 1059 ADR_FUNCTION(const char*) AdrGetSupportedFileFormats(); 1060 1061 /** 1062 * Returns a formatted string that lists the audio devices Audiere 1063 * supports. This function is DLL-safe. 1064 * 1065 * It is formatted in the following way: 1066 * 1067 * name1:description1;name2:description2;... 1068 */ 1069 ADR_FUNCTION(const char*) AdrGetSupportedAudioDevices(); 1070 1071 ADR_FUNCTION(int) AdrGetSampleSize(SampleFormat format); 1072 1073 ADR_FUNCTION(AudioDevice*) AdrOpenDevice( 1074 const char* name, 1075 const char* parameters); 1076 1077 ADR_FUNCTION(SampleSource*) AdrOpenSampleSource( 1078 const char* filename, 1079 FileFormat file_format); 1080 ADR_FUNCTION(SampleSource*) AdrOpenSampleSourceFromFile( 1081 File* file, 1082 FileFormat file_format); 1083 ADR_FUNCTION(SampleSource*) AdrCreateTone(double frequency); 1084 ADR_FUNCTION(SampleSource*) AdrCreateSquareWave(double frequency); 1085 ADR_FUNCTION(SampleSource*) AdrCreateWhiteNoise(); 1086 ADR_FUNCTION(SampleSource*) AdrCreatePinkNoise(); 1087 1088 ADR_FUNCTION(LoopPointSource*) AdrCreateLoopPointSource( 1089 SampleSource* source); 1090 1091 ADR_FUNCTION(OutputStream*) AdrOpenSound( 1092 AudioDevice* device, 1093 SampleSource* source, 1094 bool streaming); 1095 1096 ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBuffer( 1097 void* samples, 1098 int frame_count, 1099 int channel_count, 1100 int sample_rate, 1101 SampleFormat sample_format); 1102 ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBufferFromSource( 1103 SampleSource* source); 1104 1105 ADR_FUNCTION(SoundEffect*) AdrOpenSoundEffect( 1106 AudioDevice* device, 1107 SampleSource* source, 1108 SoundEffectType type); 1109 1110 ADR_FUNCTION(File*) AdrOpenFile( 1111 const char* name, 1112 bool writeable); 1113 1114 ADR_FUNCTION(File*) AdrCreateMemoryFile( 1115 const void* buffer, 1116 int size); 1117 1118 ADR_FUNCTION(const char*) AdrEnumerateCDDevices(); 1119 1120 ADR_FUNCTION(CDDevice*) AdrOpenCDDevice( 1121 const char* name); // Parameters? 1122 1123 ADR_FUNCTION(MIDIDevice*) AdrOpenMIDIDevice( 1124 const char* name); // Parameters? 1125 } 1126 1127 1128 1129 1130 /*-------- PUBLIC API FUNCTIONS --------*/ 1131 1132 1133 /** 1134 * Returns the Audiere version string. 1135 * 1136 * @return Audiere version information 1137 */ GetVersion()1138 inline const char* GetVersion() { 1139 return hidden::AdrGetVersion(); 1140 } 1141 1142 SplitString(std::vector<std::string> & out,const char * in,char delim)1143 inline void SplitString( 1144 std::vector<std::string>& out, 1145 const char* in, 1146 char delim) 1147 { 1148 out.clear(); 1149 while (*in) { 1150 const char* next = strchr(in, delim); 1151 if (next) { 1152 out.push_back(std::string(in, next)); 1153 } else { 1154 out.push_back(in); 1155 } 1156 1157 in = (next ? next + 1 : ""); 1158 } 1159 } 1160 1161 1162 /// Describes a file format that Audiere supports. 1163 struct FileFormatDesc { 1164 /// Short description of format, such as "MP3 Files" or "Mod Files" 1165 std::string description; 1166 1167 /// List of support extensions, such as {"mod", "it", "xm"} 1168 std::vector<std::string> extensions; 1169 }; 1170 1171 /// Populates a vector of FileFormatDesc structs. GetSupportedFileFormats(std::vector<FileFormatDesc> & formats)1172 inline void GetSupportedFileFormats(std::vector<FileFormatDesc>& formats) { 1173 std::vector<std::string> descriptions; 1174 SplitString(descriptions, hidden::AdrGetSupportedFileFormats(), ';'); 1175 1176 formats.resize(descriptions.size()); 1177 for (unsigned i = 0; i < descriptions.size(); ++i) { 1178 const char* d = descriptions[i].c_str(); 1179 const char* colon = strchr(d, ':'); 1180 formats[i].description.assign(d, colon); 1181 1182 SplitString(formats[i].extensions, colon + 1, ','); 1183 } 1184 } 1185 1186 1187 /// Describes a supported audio device. 1188 struct AudioDeviceDesc { 1189 /// Name of device, i.e. "directsound", "winmm", or "oss" 1190 std::string name; 1191 1192 // Textual description of device. 1193 std::string description; 1194 }; 1195 1196 /// Populates a vector of AudioDeviceDesc structs. GetSupportedAudioDevices(std::vector<AudioDeviceDesc> & devices)1197 inline void GetSupportedAudioDevices(std::vector<AudioDeviceDesc>& devices) { 1198 std::vector<std::string> descriptions; 1199 SplitString(descriptions, hidden::AdrGetSupportedAudioDevices(), ';'); 1200 1201 devices.resize(descriptions.size()); 1202 for (unsigned i = 0; i < descriptions.size(); ++i) { 1203 std::vector<std::string> d; 1204 SplitString(d, descriptions[i].c_str(), ':'); 1205 devices[i].name = d[0]; 1206 devices[i].description = d[1]; 1207 } 1208 } 1209 1210 1211 /** 1212 * Get the size of a sample in a specific sample format. 1213 * This is commonly used to determine how many bytes a chunk of 1214 * PCM data will take. 1215 * 1216 * @return Number of bytes a single sample in the specified format 1217 * takes. 1218 */ GetSampleSize(SampleFormat format)1219 inline int GetSampleSize(SampleFormat format) { 1220 return hidden::AdrGetSampleSize(format); 1221 } 1222 1223 /** 1224 * Open a new audio device. If name or parameters are not specified, 1225 * defaults are used. Each platform has its own set of audio devices. 1226 * Every platform supports the "null" audio device. 1227 * 1228 * @param name name of audio device that should be used 1229 * @param parameters comma delimited list of audio-device parameters; 1230 * for example, "buffer=100,rate=44100" 1231 * 1232 * @return new audio device object if OpenDevice succeeds, and 0 in case 1233 * of failure 1234 */ 1235 inline AudioDevice* OpenDevice( 1236 const char* name = 0, 1237 const char* parameters = 0) 1238 { 1239 return hidden::AdrOpenDevice(name, parameters); 1240 } 1241 1242 /** 1243 * Create a streaming sample source from a sound file. This factory simply 1244 * opens a default file from the system filesystem and calls 1245 * OpenSampleSource(File*). 1246 * 1247 * @see OpenSampleSource(File*) 1248 */ 1249 inline SampleSource* OpenSampleSource( 1250 const char* filename, 1251 FileFormat file_format = FF_AUTODETECT) 1252 { 1253 return hidden::AdrOpenSampleSource(filename, file_format); 1254 } 1255 1256 /** 1257 * Opens a sample source from the specified file object. If the sound file 1258 * cannot be opened, this factory function returns 0. 1259 * 1260 * @note Some sound files support seeking, while some don't. 1261 * 1262 * @param file File object from which to open the decoder 1263 * @param file_format Format of the file to load. If FF_AUTODETECT, 1264 * Audiere will try opening the file in each format. 1265 * 1266 * @return new SampleSource if OpenSampleSource succeeds, 0 otherwise 1267 */ 1268 inline SampleSource* OpenSampleSource( 1269 const FilePtr& file, 1270 FileFormat file_format = FF_AUTODETECT) 1271 { 1272 return hidden::AdrOpenSampleSourceFromFile(file.get(), file_format); 1273 } 1274 1275 /** 1276 * Create a tone sample source with the specified frequency. 1277 * 1278 * @param frequency Frequency of the tone in Hz. 1279 * 1280 * @return tone sample source 1281 */ CreateTone(double frequency)1282 inline SampleSource* CreateTone(double frequency) { 1283 return hidden::AdrCreateTone(frequency); 1284 } 1285 1286 /** 1287 * Create a square wave with the specified frequency. 1288 * 1289 * @param frequency Frequency of the wave in Hz. 1290 * 1291 * @return wave sample source 1292 */ CreateSquareWave(double frequency)1293 inline SampleSource* CreateSquareWave(double frequency) { 1294 return hidden::AdrCreateSquareWave(frequency); 1295 } 1296 1297 /** 1298 * Create a white noise sample source. White noise is just random 1299 * data. 1300 * 1301 * @return white noise sample source 1302 */ CreateWhiteNoise()1303 inline SampleSource* CreateWhiteNoise() { 1304 return hidden::AdrCreateWhiteNoise(); 1305 } 1306 1307 /** 1308 * Create a pink noise sample source. Pink noise is noise with equal 1309 * power distribution among octaves (logarithmic), not frequencies. 1310 * 1311 * @return pink noise sample source 1312 */ CreatePinkNoise()1313 inline SampleSource* CreatePinkNoise() { 1314 return hidden::AdrCreatePinkNoise(); 1315 } 1316 1317 /** 1318 * Create a LoopPointSource from a SampleSource. The SampleSource must 1319 * be seekable. If it isn't, or the source isn't valid, this function 1320 * returns 0. 1321 */ CreateLoopPointSource(const SampleSourcePtr & source)1322 inline LoopPointSource* CreateLoopPointSource( 1323 const SampleSourcePtr& source) 1324 { 1325 return hidden::AdrCreateLoopPointSource(source.get()); 1326 } 1327 1328 /** 1329 * Creates a LoopPointSource from a source loaded from a file. 1330 */ 1331 inline LoopPointSource* CreateLoopPointSource( 1332 const char* filename, 1333 FileFormat file_format = FF_AUTODETECT) 1334 { 1335 return CreateLoopPointSource(OpenSampleSource(filename, file_format)); 1336 } 1337 1338 /** 1339 * Creates a LoopPointSource from a source loaded from a file. 1340 */ 1341 inline LoopPointSource* CreateLoopPointSource( 1342 const FilePtr& file, 1343 FileFormat file_format = FF_AUTODETECT) 1344 { 1345 return CreateLoopPointSource(OpenSampleSource(file, file_format)); 1346 } 1347 1348 /** 1349 * Try to open a sound buffer using the specified AudioDevice and 1350 * sample source. If the specified sample source is seekable, it 1351 * loads it into memory and uses AudioDevice::openBuffer to create 1352 * the output stream. If the stream is not seekable, it uses 1353 * AudioDevice::openStream to create the output stream. This means 1354 * that certain file types must always be streamed, and therefore, 1355 * OpenSound will hold on to the file object. If you must guarantee 1356 * that the file on disk is no longer referenced, you must create 1357 * your own memory file implementation and load your data into that 1358 * before calling OpenSound. 1359 * 1360 * @param device AudioDevice in which to open the output stream. 1361 * 1362 * @param source SampleSource used to generate samples for the sound 1363 * object. OpenSound takes ownership of source, even 1364 * if it returns 0. (In that case, OpenSound immediately 1365 * deletes the SampleSource.) 1366 * 1367 * @param streaming If false or unspecified, OpenSound attempts to 1368 * open the entire sound into memory. Otherwise, it 1369 * streams the sound from the file. 1370 * 1371 * @return new output stream if successful, 0 otherwise 1372 */ 1373 inline OutputStream* OpenSound( 1374 const AudioDevicePtr& device, 1375 const SampleSourcePtr& source, 1376 bool streaming = false) 1377 { 1378 return hidden::AdrOpenSound(device.get(), source.get(), streaming); 1379 } 1380 1381 /** 1382 * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source 1383 * created via OpenSampleSource(const char*). 1384 */ 1385 inline OutputStream* OpenSound( 1386 const AudioDevicePtr& device, 1387 const char* filename, 1388 bool streaming = false, 1389 FileFormat file_format = FF_AUTODETECT) 1390 { 1391 SampleSource* source = OpenSampleSource(filename, file_format); 1392 return OpenSound(device, source, streaming); 1393 } 1394 1395 /** 1396 * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source 1397 * created via OpenSampleSource(File* file). 1398 */ 1399 inline OutputStream* OpenSound( 1400 const AudioDevicePtr& device, 1401 const FilePtr& file, 1402 bool streaming = false, 1403 FileFormat file_format = FF_AUTODETECT) 1404 { 1405 SampleSource* source = OpenSampleSource(file, file_format); 1406 return OpenSound(device, source, streaming); 1407 } 1408 1409 /** 1410 * Create a SampleBuffer object using the specified samples and formats. 1411 * 1412 * @param samples Pointer to a buffer of samples used to initialize the 1413 * new object. If this is 0, the sample buffer contains 1414 * just silence. 1415 * 1416 * @param frame_count Size of the sample buffer in frames. 1417 * 1418 * @param channel_count Number of channels in each frame. 1419 * 1420 * @param sample_rate Sample rate in Hz. 1421 * 1422 * @param sample_format Format of each sample. @see SampleFormat. 1423 * 1424 * @return new SampleBuffer object 1425 */ CreateSampleBuffer(void * samples,int frame_count,int channel_count,int sample_rate,SampleFormat sample_format)1426 inline SampleBuffer* CreateSampleBuffer( 1427 void* samples, 1428 int frame_count, 1429 int channel_count, 1430 int sample_rate, 1431 SampleFormat sample_format) 1432 { 1433 return hidden::AdrCreateSampleBuffer( 1434 samples, frame_count, 1435 channel_count, sample_rate, sample_format); 1436 } 1437 1438 /** 1439 * Create a SampleBuffer object from a SampleSource. 1440 * 1441 * @param source Seekable sample source used to create the buffer. 1442 * If the source is not seekable, then the function 1443 * fails. 1444 * 1445 * @return new sample buffer if success, 0 otherwise 1446 */ CreateSampleBuffer(const SampleSourcePtr & source)1447 inline SampleBuffer* CreateSampleBuffer(const SampleSourcePtr& source) { 1448 return hidden::AdrCreateSampleBufferFromSource(source.get()); 1449 } 1450 1451 /** 1452 * Open a SoundEffect object from the given sample source and sound 1453 * effect type. @see SoundEffect 1454 * 1455 * @param device AudioDevice on which the sound is played. 1456 * 1457 * @param source The sample source used to feed the sound effect 1458 * with data. 1459 * 1460 * @param type The type of the sound effect. If type is MULTIPLE, 1461 * the source must be seekable. 1462 * 1463 * @return new SoundEffect object if successful, 0 otherwise 1464 */ OpenSoundEffect(const AudioDevicePtr & device,const SampleSourcePtr & source,SoundEffectType type)1465 inline SoundEffect* OpenSoundEffect( 1466 const AudioDevicePtr& device, 1467 const SampleSourcePtr& source, 1468 SoundEffectType type) 1469 { 1470 return hidden::AdrOpenSoundEffect(device.get(), source.get(), type); 1471 } 1472 1473 /** 1474 * Calls OpenSoundEffect(AudioDevice*, SampleSource*, 1475 * SoundEffectType) with a sample source created from the filename. 1476 */ 1477 inline SoundEffect* OpenSoundEffect( 1478 const AudioDevicePtr& device, 1479 const char* filename, 1480 SoundEffectType type, 1481 FileFormat file_format = FF_AUTODETECT) 1482 { 1483 SampleSource* source = OpenSampleSource(filename, file_format); 1484 return OpenSoundEffect(device, source, type); 1485 } 1486 1487 /** 1488 * Calls OpenSoundEffect(AudioDevice*, SampleSource*, 1489 * SoundEffectType) with a sample source created from the file. 1490 */ 1491 inline SoundEffect* OpenSoundEffect( 1492 const AudioDevicePtr& device, 1493 const FilePtr& file, 1494 SoundEffectType type, 1495 FileFormat file_format = FF_AUTODETECT) 1496 { 1497 SampleSource* source = OpenSampleSource(file, file_format); 1498 return OpenSoundEffect(device, source, type); 1499 } 1500 1501 /** 1502 * Opens a default file implementation from the local filesystem. 1503 * 1504 * @param filename The name of the file on the local filesystem. 1505 * @param writeable Whether the writing to the file is allowed. 1506 */ OpenFile(const char * filename,bool writeable)1507 inline File* OpenFile(const char* filename, bool writeable) { 1508 return hidden::AdrOpenFile(filename, writeable); 1509 } 1510 1511 /** 1512 * Creates a File implementation that reads from a buffer in memory. 1513 * It stores a copy of the buffer that is passed in. 1514 * 1515 * The File object does <i>not</i> take ownership of the memory buffer. 1516 * When the file is destroyed, it will not free the memory. 1517 * 1518 * @param buffer Pointer to the beginning of the data. 1519 * @param size Size of the buffer in bytes. 1520 * 1521 * @return 0 if size is non-zero and buffer is null. Otherwise, 1522 * returns a valid File object. 1523 */ CreateMemoryFile(const void * buffer,int size)1524 inline File* CreateMemoryFile(const void* buffer, int size) { 1525 return hidden::AdrCreateMemoryFile(buffer, size); 1526 } 1527 1528 /** 1529 * Generates a list of available CD device names. 1530 * 1531 * @param devices A vector of strings to be filled. 1532 */ EnumerateCDDevices(std::vector<std::string> & devices)1533 inline void EnumerateCDDevices(std::vector<std::string>& devices) { 1534 const char* d = hidden::AdrEnumerateCDDevices(); 1535 while (d && *d) { 1536 devices.push_back(d); 1537 d += strlen(d) + 1; 1538 } 1539 } 1540 1541 /** 1542 * Opens the specified CD playback device. 1543 * 1544 * @param device The filesystem device to be played. 1545 * e.g. Linux: "/dev/cdrom", Windows: "D:" 1546 * 1547 * @return 0 if opening device failed, valid CDDrive object otherwise. 1548 */ OpenCDDevice(const char * device)1549 inline CDDevice* OpenCDDevice(const char* device) { 1550 return hidden::AdrOpenCDDevice(device); 1551 } 1552 1553 /** 1554 * Opens the specified MIDI synthesizer device. 1555 * 1556 * @param device The name of the device. Unused for now. 1557 * 1558 * @return 0 if opening device failed, valid MIDIDevice object otherwise. 1559 */ OpenMIDIDevice(const char * device)1560 inline MIDIDevice* OpenMIDIDevice(const char* device) { 1561 return hidden::AdrOpenMIDIDevice(device); 1562 } 1563 1564 } 1565 1566 1567 #endif 1568