Android Soundpool HeapSize Переполнение -- android поле с участием overflow поле с участием soundpool пол Связанный проблема

android soundpool heapsize overflow


6
vote

проблема

русский

Я получаю эту ошибку сотни раз, когда я бегу в отладку, это, похоже, не влияет на программу, но как мне избавиться от этого?

Я знаю, что его можно проследить обратно в Soundpool на основе других сообщений

09-15 09: 03: 09.190: Ошибка / audioCache (34): Размер кучи Переполнение! req size: 1052672, максимальный размер: 1048576

Английский оригинал

I get this error hundreds of times when I run in Debug, it doesn't seem to affect the program, but how do I get rid of it?

I know it can be traced back to the SoundPool based on other posts

09-15 09:03:09.190: ERROR/AudioCache(34): Heap size overflow! req size: 1052672, max size: 1048576

</div
        
       
       

Список ответов

12
 
vote

Soundpool - это жесткий код размера буфера как 1 м для всех загруженных файлов. Таким образом, вы, вероятно, получите ошибку «Размер кучи переполнения», когда вы загружаете слишком много файлов в SoundPool. У меня также есть этот вопрос в игровом проекте, который загрузит игру звука FX в Soundpool, а решение так, как следует:

  1. играть в длинную / большую фоновую музыку в MediaPlayer.
  2. Воспроизведение коротких звуковых файлов в нескольких экземплярах Soundpool, чтобы предотвратить ошибку кучи. Образец кода для Multi Soundpools:

 <код>   /**   * Multi SoundPool to prevent memory error.   */ public class SoundPools {    private static final String TAG = "SoundPools";    private static final int MAX_STREAMS_PER_POOL = 15;    private List<SoundPoolContainer> containers;    public SoundPools() {     containers = Collections.synchronizedList(new ArrayList<SoundPoolContainer>());   }    public void loadSound(Context context, String id, String file) {     Log.d(TAG, "SouldPools load sound " + file);     try {       for (SoundPoolContainer container : containers) {         if (container.contains(id)) {           return;         }       }       for (SoundPoolContainer container : containers) {         if (!container.isFull()) {           container.load(context, id, file);           return;         }       }       SoundPoolContainer container = new SoundPoolContainer();       containers.add(container);       container.load(context, id, file);     } catch (Exception e) {       Log.w(TAG, "Load sound error", e);     }   }    public void playSound(Context context, String id, String file) {     Log.d(TAG, "SouldPools play sound " + file);     try {       for (SoundPoolContainer container : containers) {         if (container.contains(id)) {           container.play(context, id, file);           return;         }       }       for (SoundPoolContainer container : containers) {         if (!container.isFull()) {           container.play(context, id, file);           return;         }       }       SoundPoolContainer container = new SoundPoolContainer();       containers.add(container);        container.play(context, id, file);     } catch (Exception e) {       Log.w(TAG, "Play sound error", e);     }   }    public void onPause() {     for (SoundPoolContainer container : containers) {       container.onPause();     }   }    public void onResume() {     for (SoundPoolContainer container : containers) {       container.onResume();     }   }    private static class SoundPoolContainer {     SoundPool soundPool;     Map<String, Integer> soundMap;     AtomicInteger size;      public SoundPoolContainer() {       this.soundPool = new SoundPool(MAX_STREAMS_PER_POOL, android.media.AudioManager.STREAM_MUSIC, 0);       this.soundMap = new ConcurrentHashMap<String, Integer>(MAX_STREAMS_PER_POOL);       this.size = new AtomicInteger(0);     }      public void load(Context context, String id, String file) {       try {         this.size.incrementAndGet();         soundMap.put(id, soundPool.load(context.getAssets().openFd(file), 1));       } catch (Exception e) {         this.size.decrementAndGet();         Log.w(TAG, "Load sound error", e);       }     }      public void play(Context context, String id, String file) {       android.media.AudioManager audioManager = (android.media.AudioManager) context           .getSystemService(Context.AUDIO_SERVICE);       final int streamVolume = audioManager.getStreamVolume(android.media.AudioManager.STREAM_MUSIC);       Integer soundId = soundMap.get(id);       if (soundId == null) {         soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {           @Override           public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {             soundPool.play(sampleId, streamVolume, streamVolume, 1, 0, 1f);           }         });         try {           this.size.incrementAndGet();           soundPool.load(context.getAssets().openFd(file), 1);         } catch (IOException e) {           this.size.decrementAndGet();           Log.w(TAG, "Load/Play sound error", e);         }       } else {         try {           soundPool.play(soundId, streamVolume, streamVolume, 1, 0, 1f);         } catch (Exception e) {           Log.w(TAG, "Play sound error", e);         }       }     }      public boolean contains(String id) {       return soundMap.containsKey(id);     }      public boolean isFull() {       return this.size.get() >= MAX_STREAMS_PER_POOL;     }      public void onPause() {       try {         soundPool.autoPause();       } catch (Exception e) {         Log.w(TAG, "Pause SoundPool error", e);       }     }      public void onResume() {       try {         soundPool.autoResume();       } catch (Exception e) {         Log.w(TAG, "Resume SoundPool error", e);       }     }   }  }   

 

SoundPool is hard code the buffer size as 1M for all loaded file. So you probably will get 'heap size overflow' error when you load too much files into SoundPool. I also have this issue on a game project that will load game sound FX into SoundPool and the solution is as follow:

  1. Play long/large background music in MediaPlayer.
  2. Play short sound files in multi SoundPool instances to prevent the heap error. The sample code for multi SoundPools:

  /**   * Multi SoundPool to prevent memory error.   */ public class SoundPools {    private static final String TAG = "SoundPools";    private static final int MAX_STREAMS_PER_POOL = 15;    private List<SoundPoolContainer> containers;    public SoundPools() {     containers = Collections.synchronizedList(new ArrayList<SoundPoolContainer>());   }    public void loadSound(Context context, String id, String file) {     Log.d(TAG, "SouldPools load sound " + file);     try {       for (SoundPoolContainer container : containers) {         if (container.contains(id)) {           return;         }       }       for (SoundPoolContainer container : containers) {         if (!container.isFull()) {           container.load(context, id, file);           return;         }       }       SoundPoolContainer container = new SoundPoolContainer();       containers.add(container);       container.load(context, id, file);     } catch (Exception e) {       Log.w(TAG, "Load sound error", e);     }   }    public void playSound(Context context, String id, String file) {     Log.d(TAG, "SouldPools play sound " + file);     try {       for (SoundPoolContainer container : containers) {         if (container.contains(id)) {           container.play(context, id, file);           return;         }       }       for (SoundPoolContainer container : containers) {         if (!container.isFull()) {           container.play(context, id, file);           return;         }       }       SoundPoolContainer container = new SoundPoolContainer();       containers.add(container);        container.play(context, id, file);     } catch (Exception e) {       Log.w(TAG, "Play sound error", e);     }   }    public void onPause() {     for (SoundPoolContainer container : containers) {       container.onPause();     }   }    public void onResume() {     for (SoundPoolContainer container : containers) {       container.onResume();     }   }    private static class SoundPoolContainer {     SoundPool soundPool;     Map<String, Integer> soundMap;     AtomicInteger size;      public SoundPoolContainer() {       this.soundPool = new SoundPool(MAX_STREAMS_PER_POOL, android.media.AudioManager.STREAM_MUSIC, 0);       this.soundMap = new ConcurrentHashMap<String, Integer>(MAX_STREAMS_PER_POOL);       this.size = new AtomicInteger(0);     }      public void load(Context context, String id, String file) {       try {         this.size.incrementAndGet();         soundMap.put(id, soundPool.load(context.getAssets().openFd(file), 1));       } catch (Exception e) {         this.size.decrementAndGet();         Log.w(TAG, "Load sound error", e);       }     }      public void play(Context context, String id, String file) {       android.media.AudioManager audioManager = (android.media.AudioManager) context           .getSystemService(Context.AUDIO_SERVICE);       final int streamVolume = audioManager.getStreamVolume(android.media.AudioManager.STREAM_MUSIC);       Integer soundId = soundMap.get(id);       if (soundId == null) {         soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {           @Override           public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {             soundPool.play(sampleId, streamVolume, streamVolume, 1, 0, 1f);           }         });         try {           this.size.incrementAndGet();           soundPool.load(context.getAssets().openFd(file), 1);         } catch (IOException e) {           this.size.decrementAndGet();           Log.w(TAG, "Load/Play sound error", e);         }       } else {         try {           soundPool.play(soundId, streamVolume, streamVolume, 1, 0, 1f);         } catch (Exception e) {           Log.w(TAG, "Play sound error", e);         }       }     }      public boolean contains(String id) {       return soundMap.containsKey(id);     }      public boolean isFull() {       return this.size.get() >= MAX_STREAMS_PER_POOL;     }      public void onPause() {       try {         soundPool.autoPause();       } catch (Exception e) {         Log.w(TAG, "Pause SoundPool error", e);       }     }      public void onResume() {       try {         soundPool.autoResume();       } catch (Exception e) {         Log.w(TAG, "Resume SoundPool error", e);       }     }   }  } 

</div
 
 
0
 
vote

Может быть, ваш медиа-ресурс слишком большой для игры с Soundpool. Soundpool играет только короткие звуковые эффекты. На API Soundpool нет спецификации о максимуме ресурса для игры с Soundpool, но если вы его используете, играйте только короткие звуковые эффекты, такие как, например, короткий взрыв в стрелке. Если это ваша проблема, вы должны использовать MediaPlayer для воспроизведения ваших звуков.

 

Maybe your media resource is too big for playing with soundpool. Soundpool only plays short sound effects. On the Soundpool API there is no specification about the maximum of a resource for playing with soundpool, but if You use it, play just short sound effects like, for example, a short explosion in a shooter game. If this is Your problem, You should use MediaPlayer for playing your sounds.

</div
 
 
0
 
vote

Это невозможно для этой ошибки о размере кучи, потому что нет никакого устройства с такой небольшой кучей 1052672 ~ 1 МБ., Но о <Код> SoundPool Размер буфера. <Код> SoundPool имеет жесткодируемый предел 1 МБ RAW PCM_16 данных в памяти. Этот предел применяется для каждого звука, который вы загружаете в память, а не для звуков в сумме на один <код> SoundPool . Так что самый голосованный ответ о <Код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 0 очень неправильный!

Позвольте мне представить <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 1 , который использует <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 2 под капотом и имел пользовательский <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 3 . Все данные в указанном буфере будут загружены в память и воспроизводиться с небольшим задержкой, такими как <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 4 делает. Все данные, которые превышают, что <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 5 будут загружены по требованию (что добавляет задержку, аналогично <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 6 ). API очень SimilArt to toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 7 , также добавлена ​​функция для загрузки звуков от URI (например, GDRive). И есть <код> toolTip.mouseover(function(){ ShowId = $(this).attr(idString); showToolTip(idHashString, ShowId); }); contentholder.mouseleave(function(){ ShowId = $(this).find('.info').attr(idString); hideToolTip(idHashString, ShowId); }); 8 метод, все ресурсы будут выгружены после воспроизведения файла.

 <код>         toolTip.mouseover(function(){                 ShowId = $(this).attr(idString);                 showToolTip(idHashString, ShowId);         });          contentholder.mouseleave(function(){             ShowId = $(this).find('.info').attr(idString);             hideToolTip(idHashString, ShowId);         }); 9  

https://gitlab.com/olekdia/common/Libraries/sound-pool

 

It is not possible for this error to be about heap size, because there aren't any device with such a small heap 1052672 ~ 1Mb., but about SoundPool buffer size. SoundPool has hardcoded limit of 1Mb of raw PCM_16 data in memory. This limit applies for every sound you are loading into memory, and not for sounds in sum per one SoundPool. So the most voted answer about SoundPools is very wrong!

Let me introduce SoundPoolCompat which uses AudioTrack under the hood and have custom bufferSize. All data within specified buffer will be loaded into memory and played with small latency like SoundPool does. All data that exceed that bufferSize will be loaded on demand (which adds latency, similar to MediaPlayer). Api is very similart to SoundPool, also it is added a feature to load sounds from Uri (for example gdrive). And there is playOnce method, all resources will be unloaded after file is played.

implementation 'com.olekdia:sound-pool:3.0.2' 

https://gitlab.com/olekdia/common/libraries/sound-pool

</div
 
 

Связанный проблема

1  Обновить и загрузить один конкретный фрагмент предыдущего действия  ( Refresh and load one particular fragment of the previous activity ) 
У меня есть 3 фрагмента в активности. Один из фрагментов отображает список предметов вместе с ценой и количеством. При выборе любого элемента появится новое д...

2  Распознавание речи Android не подключено к службе распознавания  ( Android speech recognizer not connected to the recognition service ) 
Я хочу ввести функцию постоянного распознавания голоса в моем приложении Android. Я осознаю тот факт, что распознавание голоса время от времени зависает от ...

3  Возможно ли совместное использование экрана в Cordova?  ( Is screen sharing possible in cordova ) 
Я использую Opentok для видеочата и совместного использования экрана. Это отлично работает для меня на браузере. Однако мое приложение также бежит в родом с и...

2  Как получить направление на кратчайший путь внешнего круга в Google Maps Android, когда мое текущее местоположение находится внутри 2 или более кругов?  ( How to get direction to the shortest path outside circle in google maps android ) 
Как получить направление к ближайшему расположению внешний круг, если голубые точки - текущее местоположение? 1 [ 1 и как отображать маркеры только во...

2  Держите текущую страницу, представленную, пока на следующей странице не загружена  ( Keep current page rendered until the next page is loaded ) 
У меня есть простое приложение, которое основано на WebView.loadurl (« http://www.example.com "). Когда пользователь нажимает на URL, поведение по умолчани...

0  Кэшинга не работала на работе при добавлении интернет-соединения перехвата (модернизация 2 - Android)  ( Caching didnt work work when adding internet connection interceptor retrofit 2 ) 
Я пытаюсь реализовать интернет-соединение перехватчика с кэшированием с помощью модернизации и OKHTTP. Кэширование работает нормально, не добавляя интернет-...

0  ONITEMSELUCTERLISTENER не выходит, когда я выбираю то же предыдущее значение  ( Onitemselectedlistener is not fired when i select the same previous value ) 
Когда я снова выбираю то же значение, которое в адаптере значения не обновляются и даже OnitEmseLectedListener или NothingsElected не выдержаны Вот следует ...

1  Первое приложение для Android после Eclipse Установить  ( First app for android after eclipse install ) 
Я искал вокруг и не могу найти точную ситуацию или ответить, что мне нужно, поэтому мне придется задать вопрос, что я уверен, что где-то просил там, поэтому м...

4  Как получить местное видео URI для Exoplayer 2.x  ( How to get local video uri for exoplayer 2 x ) 
У меня есть видеофайл Dog.mp4 в res/raw папка, который я хочу играть с экзоплом. Я пытаюсь выяснить, как получить видео URI для этой строки кода из Руководс...

25  Почему приложение умирает случайным образом?  ( Why application is dying randomly ) 
Я разрабатываю приложение для музыкального проигрывателя. Все работает нормально, за исключением внезапно умирает приложение. Иногда это происходит, когда при...

6  Android Gridlayout API 21  ( Android gridlayout api 21 ) 
Я пытаюсь сделать что-то вроде этого: В настоящее время я вручную устанавливаю ширину плиток, равных половине ширины экрана. Это работает хорошо, но он д...

1  Пункт меню Текст не отображается в DOWELAPPBAR  ( Menu item text not showing in bottomappbar ) 
Я пытался добавить заголовок пункт меню вместе с значком меню в нижней панели приложений в Android-студии. Я пытался установить: <код> app:showAsAction="ifR...

3  Как установить Gridlines в GridView в Android  ( How to set gridlines to a gridview in android ) 
Я использую GridView, чтобы показать сводный отчет о 3 столбцах в моем приложении. Кажется, все работает нормально, за исключением пропущенных скремок GridVie...

0  Вставить арабский с помощью PDO не работает  ( Insert arabic using pdo is not working ) 
Я очень глубоко укорую в этом и посмотрите много вопросов, и это не работает Каждый раз, когда я пытаюсь вставить арабский, он показывает так (?????) <Сильн...

-1  Как изменить странные и даже пункты меню переполнения меню  ( How to change odd and even overflow menu items background ) 
Как изменить странные и даже переполнить пункты меню фон в Android? ...

Связанный проблема

1  Обновить и загрузить один конкретный фрагмент предыдущего действия 
2  Распознавание речи Android не подключено к службе распознавания 
3  Возможно ли совместное использование экрана в Cordova? 
2  Как получить направление на кратчайший путь внешнего круга в Google Maps Android, когда мое текущее местоположение находится внутри 2 или более кругов? 
2  Держите текущую страницу, представленную, пока на следующей странице не загружена 
0  Кэшинга не работала на работе при добавлении интернет-соединения перехвата (модернизация 2 - Android) 
0  ONITEMSELUCTERLISTENER не выходит, когда я выбираю то же предыдущее значение 
1  Первое приложение для Android после Eclipse Установить 
4  Как получить местное видео URI для Exoplayer 2.x 
25  Почему приложение умирает случайным образом? 
6  Android Gridlayout API 21 
1  Пункт меню Текст не отображается в DOWELAPPBAR 
3  Как установить Gridlines в GridView в Android 
0  Вставить арабский с помощью PDO не работает 
-1  Как изменить странные и даже пункты меню переполнения меню