mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 17:47:32 -05:00
#1498 Updates JMBE audio module to retain class reference instead of reflectively loading the class each time for a new instance. Reduces pressure on both the class loader and the garbage collector. (#1499)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.audio.codec.mbe;
|
package io.github.dsheirer.audio.codec.mbe;
|
||||||
@@ -32,11 +29,6 @@ import io.github.dsheirer.message.IMessageListener;
|
|||||||
import io.github.dsheirer.preference.PreferenceType;
|
import io.github.dsheirer.preference.PreferenceType;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import jmbe.iface.IAudioCodec;
|
|
||||||
import jmbe.iface.IAudioCodecLibrary;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -44,15 +36,20 @@ import java.net.URLClassLoader;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import jmbe.iface.IAudioCodec;
|
||||||
|
import jmbe.iface.IAudioCodecLibrary;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public abstract class JmbeAudioModule extends AbstractAudioModule implements Listener<IMessage>, IMessageListener,
|
public abstract class JmbeAudioModule extends AbstractAudioModule implements Listener<IMessage>, IMessageListener,
|
||||||
ISquelchStateListener
|
ISquelchStateListener
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(JmbeAudioModule.class);
|
private static final Logger mLog = LoggerFactory.getLogger(JmbeAudioModule.class);
|
||||||
private static final String JMBE_AUDIO_LIBRARY = "JMBE";
|
private static final String JMBE_AUDIO_LIBRARY = "JMBE";
|
||||||
private static List<String> mLibraryLoadStatusLogged = new ArrayList<>();
|
private static final List<String> mLibraryLoadStatusLogged = new ArrayList<>();
|
||||||
private IAudioCodec mAudioCodec;
|
private IAudioCodec mAudioCodec;
|
||||||
private UserPreferences mUserPreferences;
|
private final UserPreferences mUserPreferences;
|
||||||
|
private static Class sLoadedJmbeAudioConverterClass;
|
||||||
|
|
||||||
public JmbeAudioModule(UserPreferences userPreferences, AliasList aliasList, int timeslot)
|
public JmbeAudioModule(UserPreferences userPreferences, AliasList aliasList, int timeslot)
|
||||||
{
|
{
|
||||||
@@ -110,38 +107,67 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
protected abstract String getCodecName();
|
protected abstract String getCodecName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads audio frame processing chain. Constructs an imbe targetdataline
|
* Loads JMBE audio converter library class and then instantiates new converter instances from the loaded class.
|
||||||
* to receive the raw imbe frames. Adds an IMBE to 8k PCM format conversion
|
|
||||||
* stream wrapper. Finally, adds an upsampling (8k to 48k) stream wrapper.
|
|
||||||
*/
|
*/
|
||||||
protected void loadConverter()
|
protected void loadConverter()
|
||||||
{
|
{
|
||||||
IAudioCodec audioConverter = null;
|
IAudioCodec audioConverter = null;
|
||||||
|
|
||||||
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
|
if(sLoadedJmbeAudioConverterClass == null)
|
||||||
|
|
||||||
if(path != null)
|
|
||||||
{
|
{
|
||||||
try
|
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
|
||||||
|
|
||||||
|
if(path != null)
|
||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.info("Loading JMBE library from [" + path.toString() + "]");
|
mLog.info("Loading JMBE library from [" + path + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
|
try
|
||||||
this.getClass().getClassLoader());
|
|
||||||
|
|
||||||
Class classToLoad = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
|
|
||||||
|
|
||||||
Object instance = classToLoad.getDeclaredConstructor().newInstance();
|
|
||||||
|
|
||||||
if(instance instanceof IAudioCodecLibrary)
|
|
||||||
{
|
{
|
||||||
IAudioCodecLibrary library = (IAudioCodecLibrary)instance;
|
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
|
||||||
|
this.getClass().getClassLoader());
|
||||||
|
|
||||||
|
sLoadedJmbeAudioConverterClass = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException iae)
|
||||||
|
{
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
|
||||||
|
{
|
||||||
|
mLog.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
|
||||||
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(MalformedURLException mue)
|
||||||
|
{
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
|
{
|
||||||
|
mLog.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
|
||||||
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(ClassNotFoundException e1)
|
||||||
|
{
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
|
{
|
||||||
|
mLog.error("Couldn't load JMBE audio conversion library - class not found");
|
||||||
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sLoadedJmbeAudioConverterClass != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object instance = sLoadedJmbeAudioConverterClass.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
if(instance instanceof IAudioCodecLibrary library)
|
||||||
|
{
|
||||||
if((library.getMajorVersion() == 1 && library.getMinorVersion() >= 0 &&
|
if((library.getMajorVersion() == 1 && library.getMinorVersion() >= 0 &&
|
||||||
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
|
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
|
||||||
{
|
{
|
||||||
audioConverter = library.getAudioConverter(getCodecName());
|
audioConverter = library.getAudioConverter(getCodecName());
|
||||||
|
|
||||||
@@ -169,38 +195,6 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(IllegalArgumentException iae)
|
|
||||||
{
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
|
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(NoSuchMethodException nsme)
|
|
||||||
{
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - no such method exception");
|
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(MalformedURLException mue)
|
|
||||||
{
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
|
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(ClassNotFoundException e1)
|
|
||||||
{
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - class not found");
|
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(InvocationTargetException ite)
|
catch(InvocationTargetException ite)
|
||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
@@ -225,6 +219,14 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch(NoSuchMethodException nsme)
|
||||||
|
{
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
|
{
|
||||||
|
mLog.error("Couldn't load JMBE audio conversion library - no such method exception");
|
||||||
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -235,13 +237,6 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(audioConverter != null)
|
mAudioCodec = audioConverter;
|
||||||
{
|
|
||||||
mAudioCodec = audioConverter;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mAudioCodec = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user