SoundOAL - Sound Datei während Laufzeit releasen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • SoundOAL - Sound Datei während Laufzeit releasen

    Hallo,
    ich habe ein kleines Problem, ich weiss nicht wie ich sounds wieder aus dem Speicher bekomme, wenn ich diese nur einmal im Programm brauche und danach gerne z.b. einen neuen Soundtrack laden möchte.

    Meine Soundfunktion habe ich mal nach Lehrbuch aufgebaut. Jetzt hätte ich gerne Funktion alla: (void) unLoadSound: (NSString*) soundName; checke aber nicht wie die aussehen muss. 8|

    Quellcode

    1. #import <Foundation/Foundation.h>
    2. #import <OpenAL/al.h>
    3. #import <OpenAL/alc.h>
    4. #import <AudioToolbox/AudioToolbox.h>
    5. @interface SoundOAL : NSObject {
    6. ALCcontext *context;
    7. ALCdevice *device;
    8. NSMutableArray *soundIDs;
    9. NSMutableDictionary *soundIDDictionary; //dynamisch
    10. NSMutableDictionary *soundBufferIDDictionary;
    11. }
    12. + (SoundOAL *) getInstance;
    13. - (void) setupOpenAL;
    14. - (void) logErrors: (OSStatus) status;
    15. - (NSUInteger) findFreeSoundID;
    16. - (void) loadSound: (NSString*) soundName
    17. Hz: (NSUInteger) sampleRate;
    18. - (void) playSound: (NSString*) soundName
    19. pitch: (float) pitch
    20. volume: (float) volume;
    21. - (void) loopSound: (NSString*) soundName
    22. pitch: (float) pitch
    23. volume: (float) volume;
    24. - (void) stopSound: (NSString*) soundName;
    25. @end
    Alles anzeigen


    und die .m:

    Quellcode

    1. #import "SoundOAL.h"
    2. @implementation SoundOAL
    3. + (SoundOAL *) getInstance {
    4. static SoundOAL *sound;
    5. @synchronized (self) {
    6. if(!sound) {
    7. sound = [[SoundOAL alloc] init];
    8. [sound setupOpenAL];
    9. }
    10. }
    11. return sound;
    12. }
    13. - (void) setupOpenAL {
    14. soundIDs = [[NSMutableArray alloc] init];
    15. soundIDDictionary = [[NSMutableDictionary alloc] init];
    16. soundBufferIDDictionary = [[NSMutableDictionary alloc] init];
    17. device = alcOpenDevice(NULL);
    18. if (device) {
    19. context = alcCreateContext(device, NULL);
    20. alcMakeContextCurrent(context);
    21. int maxSounds = 22; //Polyphonie: wir haben mehr Slots als Sounds
    22. for (int i = 0; i < maxSounds; i++) {
    23. NSUInteger soundID;
    24. alGenSources(1, &soundID); //Sound-IDs erzeugen
    25. [soundIDs addObject: [NSNumber numberWithUnsignedInt: soundID]];
    26. }
    27. [self logErrors: 0];
    28. }
    29. }
    30. //Sounddaten mit Hilfe der Audio File API einlesen (AudioToolbox)
    31. - (void) loadSound:(NSString*) soundName
    32. Hz:(NSUInteger) sampleRate {
    33. //Sound-Datei oeffnen und fileID zuweisen
    34. OSStatus status;
    35. AudioFileID fileID;
    36. NSString *path = [[NSBundle mainBundle] pathForResource: soundName ofType: nil];
    37. NSURL *afUrl = [NSURL fileURLWithPath: path];
    38. status = AudioFileOpenURL((CFURLRef) afUrl, kAudioFileReadPermission, 0, &fileID);
    39. [self logErrors: status];
    40. //Dateigroesse (fileSize) ermitteln
    41. UInt64 outDataSize = 0; //file size in bytes
    42. UInt32 thePropSize = sizeof(UInt64);
    43. status = AudioFileGetProperty(fileID, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);
    44. [self logErrors: status];
    45. UInt32 fileSize = (UInt32) outDataSize;
    46. //Sounddaten temporaer einlesen
    47. unsigned char *tempData = malloc(fileSize); //hier landen die einzelnen Samples
    48. status = AudioFileReadBytes(fileID, FALSE, 0, &fileSize, tempData);
    49. [self logErrors: status];
    50. status = AudioFileClose(fileID);
    51. //Einen neuen Audio-Buffer erzeugen
    52. NSUInteger bufferID;
    53. alGenBuffers(1, &bufferID);
    54. //Sounddaten als Raw Bytes in den Buffer schreiben (ohne Header-Information)
    55. alBufferData(bufferID, AL_FORMAT_STEREO16, tempData, fileSize, sampleRate);
    56. //Buffer in einem Dictionary ablegen
    57. [soundBufferIDDictionary setObject: [NSNumber numberWithUnsignedInt: bufferID] forKey: soundName];
    58. if(tempData) {
    59. free(tempData);
    60. tempData = NULL;
    61. }
    62. [self logErrors: status];
    63. }
    64. - (void) playSound: (NSString*) soundName
    65. pitch: (float) pitch
    66. volume: (float) volume
    67. {
    68. NSUInteger bufferID = [[soundBufferIDDictionary objectForKey: soundName] unsignedIntValue];
    69. NSUInteger soundID = [self findFreeSoundID];
    70. [soundIDDictionary setObject: [NSNumber numberWithUnsignedInt: soundID] forKey: soundName];
    71. alSourcei(soundID, AL_BUFFER, 0); //Alte Buffer-Daten loeschen
    72. alSourcei(soundID, AL_BUFFER, bufferID); //Neue Buffer-Daten an die ID binden
    73. //Sound-Eigenschaften
    74. alSourcef(soundID, AL_PITCH, pitch); // abspielgeschwindigkeits faktor
    75. alSourcef(soundID, AL_GAIN, volume); // Volume
    76. alSourcei(soundID, AL_LOOPING, AL_FALSE);
    77. alSourcePlay(soundID);
    78. [self logErrors: 0];
    79. }
    80. - (void) loopSound: (NSString*) soundName
    81. pitch: (float) pitch
    82. volume: (float) volume
    83. {
    84. NSUInteger bufferID = [[soundBufferIDDictionary objectForKey: soundName] unsignedIntValue];
    85. NSUInteger soundID = [self findFreeSoundID];
    86. [soundIDDictionary setObject: [NSNumber numberWithUnsignedInt: soundID] forKey: soundName];
    87. alSourcei(soundID, AL_BUFFER, 0); //Alte Buffer-Daten loeschen
    88. alSourcei(soundID, AL_BUFFER, bufferID); //Neue Buffer-Daten an die ID binden
    89. //Sound-Eigenschaften
    90. alSourcef(soundID, AL_PITCH, pitch);
    91. alSourcef(soundID, AL_GAIN, volume);
    92. alSourcei(soundID, AL_LOOPING, AL_TRUE);
    93. alSourcePlay(soundID);
    94. [self logErrors: 0];
    95. }
    96. - (void) stopSound: (NSString*) soundName {
    97. id obj = [soundIDDictionary objectForKey: soundName];
    98. if (obj != NULL) {
    99. NSUInteger soundID = [obj unsignedIntValue];
    100. alSourceStop(soundID);
    101. [self logErrors: 0];
    102. }
    103. }
    104. - (NSUInteger) findFreeSoundID {
    105. for (NSNumber *aSoundID in soundIDs) {
    106. NSInteger idState;
    107. alGetSourcei([aSoundID unsignedIntValue], AL_SOURCE_STATE, &idState);
    108. if(idState != AL_PLAYING) return [aSoundID unsignedIntValue];
    109. }
    110. //Wenn alle Sounds abgepspielt werden, wird der aelteste Sound ersetzt
    111. NSUInteger soundID = [[soundIDs objectAtIndex:0] unsignedIntegerValue];
    112. alSourceStop(soundID);
    113. [self logErrors: 0];
    114. return soundID;
    115. }
    116. - (void) logErrors: (OSStatus) status {
    117. ALenum err = alGetError();
    118. if (err != 0) {
    119. NSLog(@"ERROR OpenAL: %d", err);
    120. }
    121. if (status != 0) {
    122. NSLog(@"ERROR OSStatus: %ld", (long) status);
    123. }
    124. }
    125. - (void) dealloc {
    126. //Sound-IDs loeschen
    127. for(NSNumber *soundID in soundIDs) {
    128. NSUInteger sID = [soundID unsignedIntValue];
    129. alDeleteSources(1, &sID);
    130. }
    131. //Buffer-Daten loeschen
    132. NSEnumerator *enumerator = [soundBufferIDDictionary keyEnumerator];
    133. id key;
    134. while ((key = [enumerator nextObject])) {
    135. NSNumber *bufferID = [soundBufferIDDictionary objectForKey: key];
    136. NSUInteger bID = [bufferID unsignedIntValue];
    137. alDeleteBuffers(1, &bID);
    138. }
    139. [soundIDDictionary release];
    140. [soundBufferIDDictionary release];
    141. [soundIDs release];
    142. alcMakeContextCurrent(NULL);
    143. alcDestroyContext(context);
    144. alcCloseDevice(device);
    145. [self logErrors: 0];
    146. [super dealloc];
    147. }
    148. @end
    Alles anzeigen


    Hat jemand ein Codehäppchen das passt?
    VG
    Rayjunx
  • Hm, hab das so eingebaut und er meckert auch nicht und führt das "release" aus aber dennoch hängt sich die App auf wenn ich zu viele Sound Daten lade obwohl ich sie danach immer wieder release, offenbar wird der verbrauchte Platz doch nicht freigegeben. Habe es so eingebaut:

    Quellcode

    1. - (void) releaseSound: (NSString*) soundName {
    2. id obj = [soundIDDictionary objectForKey: soundName];
    3. if (obj != NULL) {
    4. NSUInteger soundID = [obj unsignedIntValue];
    5. alSourceStop(soundID);
    6. alSourcei(soundID, AL_BUFFER, NULL);
    7. [self logErrors: 0];
    8. }
    9. }