comparison src/audio/SDL_audio.c @ 2866:e532417a6977

Fixed SDL 1.2 compatibility problem. The API specifies that SDL_OpenAudio() will fill out the 'desired' audio spec with the correct samples and size set by the driver. This value is important since it may be used by applications that size audio buffers, etc. However, we want to allow advanced applications to call SDL_OpenAudioDevice() which gets passed a const 'desired' parameter, and have the correct data filled into the 'obtained' parameter, possibly allowing or not allowing format changes. So... 'obtained' becomes the audio format the user callback is expected to use, and we add flags to allow the application to specify which format changes are allowed. Note: We really need to add a way to query the 'obtained' audio spec.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 13 Dec 2008 06:36:47 +0000
parents 99210400e8b9
children 2929ed239d2a
comparison
equal deleted inserted replaced
2865:09adf4854163 2866:e532417a6977
790 } 790 }
791 791
792 792
793 static SDL_AudioDeviceID 793 static SDL_AudioDeviceID
794 open_audio_device(const char *devname, int iscapture, 794 open_audio_device(const char *devname, int iscapture,
795 const SDL_AudioSpec * _desired, SDL_AudioSpec * obtained, 795 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
796 int min_id) 796 int allowed_changes, int min_id)
797 { 797 {
798 SDL_AudioDeviceID id = 0; 798 SDL_AudioDeviceID id = 0;
799 SDL_AudioSpec desired; 799 SDL_AudioSpec _obtained;
800 SDL_AudioDevice *device; 800 SDL_AudioDevice *device;
801 SDL_bool build_cvt;
801 int i = 0; 802 int i = 0;
802 803
803 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 804 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
804 SDL_SetError("Audio subsystem is not initialized"); 805 SDL_SetError("Audio subsystem is not initialized");
805 return 0; 806 return 0;
808 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { 809 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
809 SDL_SetError("No capture support"); 810 SDL_SetError("No capture support");
810 return 0; 811 return 0;
811 } 812 }
812 813
813 if (!prepare_audiospec(_desired, &desired)) { 814 if (!obtained) {
815 obtained = &_obtained;
816 }
817 if (!prepare_audiospec(desired, obtained)) {
814 return 0; 818 return 0;
815 } 819 }
816 820
817 /* If app doesn't care about a specific device, let the user override. */ 821 /* If app doesn't care about a specific device, let the user override. */
818 if (devname == NULL) { 822 if (devname == NULL) {
863 if (device == NULL) { 867 if (device == NULL) {
864 SDL_OutOfMemory(); 868 SDL_OutOfMemory();
865 return 0; 869 return 0;
866 } 870 }
867 SDL_memset(device, '\0', sizeof(SDL_AudioDevice)); 871 SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
868 SDL_memcpy(&device->spec, &desired, sizeof(SDL_AudioSpec)); 872 device->spec = *obtained;
869 device->enabled = 1; 873 device->enabled = 1;
870 device->paused = 1; 874 device->paused = 1;
871 device->iscapture = iscapture; 875 device->iscapture = iscapture;
872 876
873 /* Create a semaphore for locking the sound buffers */ 877 /* Create a semaphore for locking the sound buffers */
884 close_audio_device(device); 888 close_audio_device(device);
885 return 0; 889 return 0;
886 } 890 }
887 device->opened = 1; 891 device->opened = 1;
888 892
889 /* If the audio driver changes the buffer size, accept it */
890 if (device->spec.samples != desired.samples) {
891 desired.samples = device->spec.samples;
892 SDL_CalculateAudioSpec(&device->spec);
893 }
894
895 /* Allocate a fake audio memory buffer */ 893 /* Allocate a fake audio memory buffer */
896 device->fake_stream = SDL_AllocAudioMem(device->spec.size); 894 device->fake_stream = SDL_AllocAudioMem(device->spec.size);
897 if (device->fake_stream == NULL) { 895 if (device->fake_stream == NULL) {
898 close_audio_device(device); 896 close_audio_device(device);
899 SDL_OutOfMemory(); 897 SDL_OutOfMemory();
900 return 0; 898 return 0;
901 } 899 }
902 900
901 /* If the audio driver changes the buffer size, accept it */
902 if (device->spec.samples != obtained->samples) {
903 obtained->samples = device->spec.samples;
904 SDL_CalculateAudioSpec(obtained);
905 }
906
903 /* See if we need to do any conversion */ 907 /* See if we need to do any conversion */
904 if (obtained != NULL) { 908 build_cvt = SDL_FALSE;
905 SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec)); 909 if (obtained->freq != device->spec.freq) {
906 } else if (desired.freq != device->spec.freq || 910 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
907 desired.format != device->spec.format || 911 obtained->freq = device->spec.freq;
908 desired.channels != device->spec.channels) { 912 } else {
913 build_cvt = SDL_TRUE;
914 }
915 }
916 if (obtained->format != device->spec.format) {
917 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
918 obtained->format = device->spec.format;
919 } else {
920 build_cvt = SDL_TRUE;
921 }
922 }
923 if (obtained->channels != device->spec.channels) {
924 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
925 obtained->channels = device->spec.channels;
926 } else {
927 build_cvt = SDL_TRUE;
928 }
929 }
930 if (build_cvt) {
909 /* Build an audio conversion block */ 931 /* Build an audio conversion block */
910 if (SDL_BuildAudioCVT(&device->convert, 932 if (SDL_BuildAudioCVT(&device->convert,
911 desired.format, desired.channels, 933 obtained->format, obtained->channels,
912 desired.freq, 934 obtained->freq,
913 device->spec.format, device->spec.channels, 935 device->spec.format, device->spec.channels,
914 device->spec.freq) < 0) { 936 device->spec.freq) < 0) {
915 close_audio_device(device); 937 close_audio_device(device);
916 return 0; 938 return 0;
917 } 939 }
918 if (device->convert.needed) { 940 if (device->convert.needed) {
919 device->convert.len = (int) (((double) desired.size) / 941 device->convert.len = (int) (((double) obtained->size) /
920 device->convert.len_ratio); 942 device->convert.len_ratio);
921 943
922 device->convert.buf = 944 device->convert.buf =
923 (Uint8 *) SDL_AllocAudioMem(device->convert.len * 945 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
924 device->convert.len_mult); 946 device->convert.len_mult);
964 return id + 1; 986 return id + 1;
965 } 987 }
966 988
967 989
968 int 990 int
969 SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained) 991 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
970 { 992 {
971 SDL_AudioDeviceID id = 0; 993 SDL_AudioDeviceID id = 0;
972 994
973 /* Start up the audio driver, if necessary. This is legacy behaviour! */ 995 /* Start up the audio driver, if necessary. This is legacy behaviour! */
974 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 996 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
981 if (open_devices[0] != NULL) { 1003 if (open_devices[0] != NULL) {
982 SDL_SetError("Audio device is already opened"); 1004 SDL_SetError("Audio device is already opened");
983 return (-1); 1005 return (-1);
984 } 1006 }
985 1007
986 id = open_audio_device(NULL, 0, desired, obtained, 1); 1008 if (obtained) {
1009 id = open_audio_device(NULL, 0, desired, obtained,
1010 SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1011 } else {
1012 id = open_audio_device(NULL, 0, desired, desired, 0, 1);
1013 }
987 if (id > 1) { /* this should never happen in theory... */ 1014 if (id > 1) { /* this should never happen in theory... */
988 SDL_CloseAudioDevice(id); 1015 SDL_CloseAudioDevice(id);
989 SDL_SetError("Internal error"); /* MUST be Device ID #1! */ 1016 SDL_SetError("Internal error"); /* MUST be Device ID #1! */
990 return (-1); 1017 return (-1);
991 } 1018 }
993 return ((id == 0) ? -1 : 0); 1020 return ((id == 0) ? -1 : 0);
994 } 1021 }
995 1022
996 SDL_AudioDeviceID 1023 SDL_AudioDeviceID
997 SDL_OpenAudioDevice(const char *device, int iscapture, 1024 SDL_OpenAudioDevice(const char *device, int iscapture,
998 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained) 1025 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
999 { 1026 int allowed_changes)
1000 return open_audio_device(device, iscapture, desired, obtained, 2); 1027 {
1028 return open_audio_device(device, iscapture, desired, obtained,
1029 allowed_changes, 2);
1001 } 1030 }
1002 1031
1003 SDL_audiostatus 1032 SDL_audiostatus
1004 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid) 1033 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1005 { 1034 {