[DEV] add basic AIRTAUDIO interface for android sound
This commit is contained in:
parent
9f4bd697e8
commit
4be5c84b9c
2
build
2
build
@ -1 +1 @@
|
|||||||
Subproject commit 2ab328a164b3c4b39df2f9b93fa0da64faf98783
|
Subproject commit b48a5672b6c3a981160bb5ec61df46cde8d823a9
|
2
external/airtaudio
vendored
2
external/airtaudio
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 56836c78767759c202ca8cf79e13e05fb0a7ae7a
|
Subproject commit a1f0b0f81c895b946a6db763d9845acdd2d05525
|
2
external/eaudiofx
vendored
2
external/eaudiofx
vendored
@ -1 +1 @@
|
|||||||
Subproject commit baf70033f33a1fc3c78159162c5d6f5193cb3840
|
Subproject commit 5f94203fff63da9a37122f550e749d3d41e88ea4
|
2
external/ejson
vendored
2
external/ejson
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 74f13fd91904cf52b4545440bfc13f5aaa827355
|
Subproject commit 989ced9c90865dda4b0d6d65a4cf7eef99d9a8c1
|
@ -56,10 +56,13 @@ import org.ewol.Ewol;
|
|||||||
public abstract class EwolActivity extends Activity implements EwolCallback, EwolConstants {
|
public abstract class EwolActivity extends Activity implements EwolCallback, EwolConstants {
|
||||||
private static Context mContext;
|
private static Context mContext;
|
||||||
private EwolSurfaceViewGL mGLView;
|
private EwolSurfaceViewGL mGLView;
|
||||||
|
private Ewol EWOL;
|
||||||
|
// clipboard section
|
||||||
|
private String tmpClipBoard; // TODO : Remove this ==> clipboard acces does not work
|
||||||
|
// Audio section :
|
||||||
private EwolAudioTask mStreams;
|
private EwolAudioTask mStreams;
|
||||||
private Thread mAudioThread;
|
private Thread mAudioThread;
|
||||||
private Ewol EWOL;
|
private boolean mAudioStarted;
|
||||||
private String tmpClipBoard; // TODO : Remove this ==> clipboard acces does not work
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
System.loadLibrary("ewol");
|
System.loadLibrary("ewol");
|
||||||
@ -99,7 +102,8 @@ public abstract class EwolActivity extends Activity implements EwolCallback, Ewo
|
|||||||
@Override protected void onCreate(Bundle savedInstanceState) {
|
@Override protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
//setListnerToRootView();
|
//setListnerToRootView();
|
||||||
|
mAudioStarted = false;
|
||||||
|
mAudioThread = null;
|
||||||
EwolActivity.mContext = getApplicationContext();
|
EwolActivity.mContext = getApplicationContext();
|
||||||
|
|
||||||
// Load the application directory
|
// Load the application directory
|
||||||
@ -147,19 +151,25 @@ public abstract class EwolActivity extends Activity implements EwolCallback, Ewo
|
|||||||
@Override protected void onResume() {
|
@Override protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mGLView.onResume();
|
mGLView.onResume();
|
||||||
/*
|
if (mAudioStarted == true) {
|
||||||
|
Log.e("EwolActivity", "Start audio interface");
|
||||||
|
if (mAudioThread == null) {
|
||||||
|
Log.e("EwolActivity", "create thread with stream");
|
||||||
mAudioThread = new Thread(mStreams);
|
mAudioThread = new Thread(mStreams);
|
||||||
if (mAudioThread != null) {
|
if (mAudioThread != null) {
|
||||||
|
Log.e("EwolActivity", "start audio");
|
||||||
mAudioThread.start();
|
mAudioThread.start();
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
}
|
||||||
EWOL.onResume();
|
EWOL.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onPause() {
|
@Override protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mGLView.onPause();
|
mGLView.onPause();
|
||||||
/*
|
if (mAudioStarted == true) {
|
||||||
|
Log.e("EwolActivity", "Pause audio interface");
|
||||||
if (mAudioThread != null) {
|
if (mAudioThread != null) {
|
||||||
// request audio stop
|
// request audio stop
|
||||||
mStreams.AutoStop();
|
mStreams.AutoStop();
|
||||||
@ -167,8 +177,9 @@ public abstract class EwolActivity extends Activity implements EwolCallback, Ewo
|
|||||||
try {
|
try {
|
||||||
mAudioThread.join();
|
mAudioThread.join();
|
||||||
} catch(InterruptedException e) { }
|
} catch(InterruptedException e) { }
|
||||||
|
mAudioThread = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
EWOL.onPause();
|
EWOL.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +325,52 @@ public abstract class EwolActivity extends Activity implements EwolCallback, Ewo
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int audioGetDeviceCount() {
|
||||||
|
//Log.e("EwolActivity", "Get device List");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String audioGetDeviceProperty(int idDevice) {
|
||||||
|
if (idDevice == 0) {
|
||||||
|
return "speaker:out:8000,16000,24000,32000,48000,96000:2:s16";
|
||||||
|
} else {
|
||||||
|
return "::::";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean audioOpenDevice(int idDevice, int freq, int nbChannel, int format) {
|
||||||
|
if (idDevice == 0) {
|
||||||
|
mAudioStarted = true;
|
||||||
|
mAudioThread = new Thread(mStreams);
|
||||||
|
if (mAudioThread != null) {
|
||||||
|
mAudioThread.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Log.e("EwolActivity", "can not open : error unknow device ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean audioCloseDevice(int idDevice) {
|
||||||
|
if (idDevice == 0) {
|
||||||
|
if (mAudioThread != null) {
|
||||||
|
// request audio stop
|
||||||
|
mStreams.AutoStop();
|
||||||
|
// wait the thread ended ...
|
||||||
|
try {
|
||||||
|
mAudioThread.join();
|
||||||
|
} catch(InterruptedException e) { }
|
||||||
|
mAudioThread = null;
|
||||||
|
}
|
||||||
|
mAudioStarted = false;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Log.e("EwolActivity", "can not close : error unknow device ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import android.media.AudioTrack;
|
|||||||
import android.media.AudioFormat;
|
import android.media.AudioFormat;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioRecord;
|
import android.media.AudioRecord;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
// import the ewol package :
|
// import the ewol package :
|
||||||
/* no need in same package... */
|
/* no need in same package... */
|
||||||
@ -30,10 +31,13 @@ public class EwolAudioTask implements Runnable, EwolConstants
|
|||||||
// constructor :
|
// constructor :
|
||||||
public EwolAudioTask(Ewol ewolInstance) {
|
public EwolAudioTask(Ewol ewolInstance) {
|
||||||
EWOL = ewolInstance;
|
EWOL = ewolInstance;
|
||||||
|
m_stopAudioThreads = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
Log.e("audioEWOL", "RUN (start)");
|
||||||
if(m_musicTrack != null) {
|
if(m_musicTrack != null) {
|
||||||
|
Log.e("audioEWOL", " ==> rejected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,18 +56,28 @@ public class EwolAudioTask implements Runnable, EwolConstants
|
|||||||
bufferSize,
|
bufferSize,
|
||||||
AudioTrack.MODE_STREAM);
|
AudioTrack.MODE_STREAM);
|
||||||
m_musicTrack.play();
|
m_musicTrack.play();
|
||||||
|
m_stopAudioThreads = false;
|
||||||
//m_musicTrack.setPositionNotificationPeriod(2048);
|
//m_musicTrack.setPositionNotificationPeriod(2048);
|
||||||
|
|
||||||
while (!m_stopAudioThreads) {
|
while (!m_stopAudioThreads) {
|
||||||
// Fill buffer with PCM data from C++
|
// Fill buffer with PCM data from C++
|
||||||
EWOL.audioPlayback(streamBuffer, NATIVE_AUDIO_BUFFER_SIZE, nbChannels);
|
EWOL.audioPlayback(streamBuffer, NATIVE_AUDIO_BUFFER_SIZE, nbChannels);
|
||||||
|
int xxx = NATIVE_AUDIO_BUFFER_SIZE;
|
||||||
|
/*
|
||||||
|
while (xxx>0) {
|
||||||
|
Log.e("audioEWOL", (NATIVE_AUDIO_BUFFER_SIZE-xxx) + " data : " + streamBuffer[NATIVE_AUDIO_BUFFER_SIZE-xxx]);
|
||||||
|
xxx--;
|
||||||
|
}
|
||||||
|
*/
|
||||||
// Stream PCM data into the music AudioTrack
|
// Stream PCM data into the music AudioTrack
|
||||||
m_musicTrack.write(streamBuffer, 0, NATIVE_AUDIO_BUFFER_SIZE);
|
m_musicTrack.write(streamBuffer, 0, NATIVE_AUDIO_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_musicTrack.flush();
|
m_musicTrack.flush();
|
||||||
m_musicTrack.stop();
|
m_musicTrack.stop();
|
||||||
|
m_musicTrack = null;
|
||||||
|
streamBuffer = null;
|
||||||
|
Log.e("audioEWOL", "RUN (stop)");
|
||||||
}
|
}
|
||||||
public void Pause() {
|
public void Pause() {
|
||||||
if(m_musicTrack == null) {
|
if(m_musicTrack == null) {
|
||||||
|
@ -15,6 +15,8 @@ public interface EwolCallback {
|
|||||||
public void orientationUpdate(int screenMode);
|
public void orientationUpdate(int screenMode);
|
||||||
public void titleSet(String value);
|
public void titleSet(String value);
|
||||||
public void stop();
|
public void stop();
|
||||||
public String getClipBoardString();
|
public int audioGetDeviceCount();
|
||||||
public void setClipBoardString(String data);
|
public String audioGetDeviceProperty(int idDevice);
|
||||||
|
public boolean audioOpenDevice(int idDevice, int freq, int nbChannel, int format);
|
||||||
|
public boolean audioCloseDevice(int idDevice);
|
||||||
}
|
}
|
||||||
|
@ -188,4 +188,24 @@ public abstract class EwolWallpaper extends WallpaperService implements EwolCall
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
Log.d("EwolCallback", "STOP is not implemented ...");
|
Log.d("EwolCallback", "STOP is not implemented ...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int audioGetDeviceCount() {
|
||||||
|
Log.e("EwolActivity", "Get device List");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String audioGetDeviceProperty(int idDevice) {
|
||||||
|
Log.e("EwolActivity", "Get device property");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean audioOpenDevice(int idDevice, int freq, int nbChannel, int format) {
|
||||||
|
Log.e("EwolActivity", "Open device");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean audioCloseDevice(int idDevice) {
|
||||||
|
Log.e("EwolActivity", "Close device");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ int64_t ewol::getTime(void) {
|
|||||||
|
|
||||||
static JavaVM* g_JavaVM=NULL; // global acces on the unique JVM !!!
|
static JavaVM* g_JavaVM=NULL; // global acces on the unique JVM !!!
|
||||||
etk::Mutex g_interfaceMutex;
|
etk::Mutex g_interfaceMutex;
|
||||||
|
etk::Mutex g_interfaceAudioMutex;
|
||||||
|
|
||||||
|
|
||||||
void java_check_exception(JNIEnv* _env) {
|
void java_check_exception(JNIEnv* _env) {
|
||||||
@ -64,6 +65,11 @@ class AndroidContext : public ewol::Context {
|
|||||||
jmethodID m_javaMethodEwolActivitySetTitle;
|
jmethodID m_javaMethodEwolActivitySetTitle;
|
||||||
jmethodID m_javaMethodEwolActivitySetClipBoardString;
|
jmethodID m_javaMethodEwolActivitySetClipBoardString;
|
||||||
jmethodID m_javaMethodEwolActivityGetClipBoardString;
|
jmethodID m_javaMethodEwolActivityGetClipBoardString;
|
||||||
|
// List of all Audio interface :
|
||||||
|
jmethodID m_javaMethodEwolActivityAudioGetDeviceCount;
|
||||||
|
jmethodID m_javaMethodEwolActivityAudioGetDeviceProperty;
|
||||||
|
jmethodID m_javaMethodEwolActivityAudioOpenDevice;
|
||||||
|
jmethodID m_javaMethodEwolActivityAudioCloseDevice;
|
||||||
jclass m_javaDefaultClassString; //!< default string class
|
jclass m_javaDefaultClassString; //!< default string class
|
||||||
int32_t m_currentHeight;
|
int32_t m_currentHeight;
|
||||||
ewol::key::Special m_guiKeyBoardSpecialKeyMode;//!< special key of the android system :
|
ewol::key::Special m_guiKeyBoardSpecialKeyMode;//!< special key of the android system :
|
||||||
@ -93,9 +99,15 @@ class AndroidContext : public ewol::Context {
|
|||||||
m_javaMethodEwolActivitySetTitle(0),
|
m_javaMethodEwolActivitySetTitle(0),
|
||||||
m_javaMethodEwolActivitySetClipBoardString(0),
|
m_javaMethodEwolActivitySetClipBoardString(0),
|
||||||
m_javaMethodEwolActivityGetClipBoardString(0),
|
m_javaMethodEwolActivityGetClipBoardString(0),
|
||||||
|
m_javaMethodEwolActivityAudioGetDeviceCount(0),
|
||||||
|
m_javaMethodEwolActivityAudioGetDeviceProperty(0),
|
||||||
|
m_javaMethodEwolActivityAudioOpenDevice(0),
|
||||||
|
m_javaMethodEwolActivityAudioCloseDevice(0),
|
||||||
m_javaDefaultClassString(0),
|
m_javaDefaultClassString(0),
|
||||||
m_currentHeight(0),
|
m_currentHeight(0),
|
||||||
m_clipBoardOwnerStd(false) {
|
m_clipBoardOwnerStd(false),
|
||||||
|
m_audioCallBack(NULL),
|
||||||
|
m_audioCallBackUserData(NULL) {
|
||||||
EWOL_DEBUG("*******************************************");
|
EWOL_DEBUG("*******************************************");
|
||||||
if (m_javaApplicationType == appl_application) {
|
if (m_javaApplicationType == appl_application) {
|
||||||
EWOL_DEBUG("** set JVM Pointer (application) **");
|
EWOL_DEBUG("** set JVM Pointer (application) **");
|
||||||
@ -122,6 +134,7 @@ class AndroidContext : public ewol::Context {
|
|||||||
m_JavaVirtualMachinePointer = NULL;
|
m_JavaVirtualMachinePointer = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool functionCallbackIsMissing = false;
|
||||||
bool ret= false;
|
bool ret= false;
|
||||||
ret = safeInitMethodID(m_javaMethodEwolActivitySetTitle,
|
ret = safeInitMethodID(m_javaMethodEwolActivitySetTitle,
|
||||||
m_javaClassEwolCallback,
|
m_javaClassEwolCallback,
|
||||||
@ -129,7 +142,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"(Ljava/lang/String;)V");
|
"(Ljava/lang/String;)V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : titleSet");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolCallbackStop,
|
ret = safeInitMethodID(m_javaMethodEwolCallbackStop,
|
||||||
@ -138,7 +152,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"()V");
|
"()V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : stop");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolCallbackEventNotifier,
|
ret = safeInitMethodID(m_javaMethodEwolCallbackEventNotifier,
|
||||||
@ -147,7 +162,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"([Ljava/lang/String;)V");
|
"([Ljava/lang/String;)V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : eventNotifier");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolCallbackKeyboardUpdate,
|
ret = safeInitMethodID(m_javaMethodEwolCallbackKeyboardUpdate,
|
||||||
@ -156,7 +172,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"(Z)V");
|
"(Z)V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : keyboardUpdate");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolCallbackOrientationUpdate,
|
ret = safeInitMethodID(m_javaMethodEwolCallbackOrientationUpdate,
|
||||||
@ -165,7 +182,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"(I)V");
|
"(I)V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : orientationUpdate");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolActivitySetClipBoardString,
|
ret = safeInitMethodID(m_javaMethodEwolActivitySetClipBoardString,
|
||||||
@ -174,7 +192,8 @@ class AndroidContext : public ewol::Context {
|
|||||||
"(Ljava/lang/String;)V");
|
"(Ljava/lang/String;)V");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : setClipBoardString");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safeInitMethodID(m_javaMethodEwolActivityGetClipBoardString,
|
ret = safeInitMethodID(m_javaMethodEwolActivityGetClipBoardString,
|
||||||
@ -183,18 +202,64 @@ class AndroidContext : public ewol::Context {
|
|||||||
"()Ljava/lang/String;");
|
"()Ljava/lang/String;");
|
||||||
if (ret == false) {
|
if (ret == false) {
|
||||||
java_check_exception(_env);
|
java_check_exception(_env);
|
||||||
return;
|
EWOL_ERROR("system can not start without function : getClipBoardString");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safeInitMethodID(m_javaMethodEwolActivityAudioGetDeviceCount,
|
||||||
|
m_javaClassEwolCallback,
|
||||||
|
"audioGetDeviceCount",
|
||||||
|
"()I");
|
||||||
|
if (ret == false) {
|
||||||
|
java_check_exception(_env);
|
||||||
|
EWOL_ERROR("system can not start without function : audioGetDeviceCount");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safeInitMethodID(m_javaMethodEwolActivityAudioGetDeviceProperty,
|
||||||
|
m_javaClassEwolCallback,
|
||||||
|
"audioGetDeviceProperty",
|
||||||
|
"(I)Ljava/lang/String;");
|
||||||
|
if (ret == false) {
|
||||||
|
java_check_exception(_env);
|
||||||
|
EWOL_ERROR("system can not start without function : audioGetDeviceProperty");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safeInitMethodID(m_javaMethodEwolActivityAudioOpenDevice,
|
||||||
|
m_javaClassEwolCallback,
|
||||||
|
"audioOpenDevice",
|
||||||
|
"(IIII)Z");
|
||||||
|
if (ret == false) {
|
||||||
|
java_check_exception(_env);
|
||||||
|
EWOL_ERROR("system can not start without function : audioOpenDevice");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
ret = safeInitMethodID(m_javaMethodEwolActivityAudioCloseDevice,
|
||||||
|
m_javaClassEwolCallback,
|
||||||
|
"audioCloseDevice",
|
||||||
|
"(I)Z");
|
||||||
|
if (ret == false) {
|
||||||
|
java_check_exception(_env);
|
||||||
|
EWOL_ERROR("system can not start without function : audioCloseDevice");
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_javaObjectEwolCallback = _env->NewGlobalRef(_objCallback);
|
m_javaObjectEwolCallback = _env->NewGlobalRef(_objCallback);
|
||||||
//javaObjectEwolCallbackAndActivity = objCallback;
|
//javaObjectEwolCallbackAndActivity = objCallback;
|
||||||
|
if (m_javaObjectEwolCallback == NULL) {
|
||||||
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_javaDefaultClassString = m_JavaVirtualMachinePointer->FindClass("java/lang/String" );
|
m_javaDefaultClassString = m_JavaVirtualMachinePointer->FindClass("java/lang/String" );
|
||||||
if (m_javaDefaultClassString == 0) {
|
if (m_javaDefaultClassString == 0) {
|
||||||
EWOL_ERROR("C->java : Can't find java/lang/String" );
|
EWOL_ERROR("C->java : Can't find java/lang/String" );
|
||||||
// remove access on the virtual machine :
|
// remove access on the virtual machine :
|
||||||
m_JavaVirtualMachinePointer = NULL;
|
m_JavaVirtualMachinePointer = NULL;
|
||||||
return;
|
functionCallbackIsMissing = true;
|
||||||
|
}
|
||||||
|
if (functionCallbackIsMissing == true) {
|
||||||
|
EWOL_CRITICAL(" mission one function ==> system can not work withut it...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -281,6 +346,110 @@ class AndroidContext : public ewol::Context {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int32_t audioGetDeviceCount(void) {
|
||||||
|
// Request the clipBoard :
|
||||||
|
EWOL_DEBUG("C->java : audio get device count");
|
||||||
|
if (m_javaApplicationType == appl_application) {
|
||||||
|
int status;
|
||||||
|
if(!java_attach_current_thread(&status)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EWOL_DEBUG("Call CallIntMethod ...");
|
||||||
|
//Call java ...
|
||||||
|
jint ret = m_JavaVirtualMachinePointer->CallIntMethod(m_javaObjectEwolCallback, m_javaMethodEwolActivityAudioGetDeviceCount);
|
||||||
|
// manage execption :
|
||||||
|
java_check_exception(m_JavaVirtualMachinePointer);
|
||||||
|
java_detach_current_thread(status);
|
||||||
|
return (int32_t)ret;
|
||||||
|
} else {
|
||||||
|
EWOL_ERROR("C->java : can not get audio device count");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::string audioGetDeviceProperty(int32_t _idDevice) {
|
||||||
|
// Request the clipBoard :
|
||||||
|
EWOL_DEBUG("C->java : audio get device count");
|
||||||
|
if (m_javaApplicationType == appl_application) {
|
||||||
|
int status;
|
||||||
|
if(!java_attach_current_thread(&status)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
//Call java ...
|
||||||
|
jstring returnString = (jstring) m_JavaVirtualMachinePointer->CallObjectMethod(m_javaObjectEwolCallback, m_javaMethodEwolActivityAudioGetDeviceProperty, _idDevice);
|
||||||
|
const char *js = m_JavaVirtualMachinePointer->GetStringUTFChars(returnString, NULL);
|
||||||
|
std::string retString(js);
|
||||||
|
m_JavaVirtualMachinePointer->ReleaseStringUTFChars(returnString, js);
|
||||||
|
//m_JavaVirtualMachinePointer->DeleteLocalRef(returnString);
|
||||||
|
// manage execption :
|
||||||
|
java_check_exception(m_JavaVirtualMachinePointer);
|
||||||
|
java_detach_current_thread(status);
|
||||||
|
return retString;
|
||||||
|
} else {
|
||||||
|
EWOL_ERROR("C->java : can not get audio device count");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
AndroidAudioCallback m_audioCallBack;
|
||||||
|
void* m_audioCallBackUserData;
|
||||||
|
public:
|
||||||
|
bool audioOpenDevice(int32_t _idDevice,
|
||||||
|
int32_t _freq,
|
||||||
|
int32_t _nbChannel,
|
||||||
|
int32_t _format,
|
||||||
|
AndroidAudioCallback _callback,
|
||||||
|
void* _userData) {
|
||||||
|
if (m_audioCallBack != NULL) {
|
||||||
|
EWOL_ERROR("AudioCallback already started ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Request the clipBoard :
|
||||||
|
EWOL_DEBUG("C->java : audio get device count");
|
||||||
|
if (m_javaApplicationType == appl_application) {
|
||||||
|
int status;
|
||||||
|
if(!java_attach_current_thread(&status)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//Call java ...
|
||||||
|
jboolean ret = m_JavaVirtualMachinePointer->CallBooleanMethod(m_javaObjectEwolCallback, m_javaMethodEwolActivityAudioOpenDevice, _idDevice, _freq, _nbChannel, _format);
|
||||||
|
// manage execption :
|
||||||
|
java_check_exception(m_JavaVirtualMachinePointer);
|
||||||
|
java_detach_current_thread(status);
|
||||||
|
if (ret == true) {
|
||||||
|
m_audioCallBack = _callback;
|
||||||
|
m_audioCallBackUserData = _userData;
|
||||||
|
}
|
||||||
|
return (bool)ret;
|
||||||
|
} else {
|
||||||
|
EWOL_ERROR("C->java : can not get audio device count");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool audioCloseDevice(int32_t _idDevice) {
|
||||||
|
if (m_audioCallBack == NULL) {
|
||||||
|
EWOL_ERROR("AudioCallback Not started ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Request the clipBoard :
|
||||||
|
EWOL_DEBUG("C->java : audio get device count");
|
||||||
|
if (m_javaApplicationType == appl_application) {
|
||||||
|
int status;
|
||||||
|
if(!java_attach_current_thread(&status)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//Call java ...
|
||||||
|
jboolean ret = m_JavaVirtualMachinePointer->CallBooleanMethod(m_javaObjectEwolCallback, m_javaMethodEwolActivityAudioCloseDevice, _idDevice);
|
||||||
|
// manage execption :
|
||||||
|
java_check_exception(m_JavaVirtualMachinePointer);
|
||||||
|
java_detach_current_thread(status);
|
||||||
|
m_audioCallBack = NULL;
|
||||||
|
m_audioCallBackUserData = NULL;
|
||||||
|
return (bool)ret;
|
||||||
|
} else {
|
||||||
|
EWOL_ERROR("C->java : can not get audio device count");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
bool java_attach_current_thread(int *_rstatus) {
|
bool java_attach_current_thread(int *_rstatus) {
|
||||||
EWOL_DEBUG("C->java : call java");
|
EWOL_DEBUG("C->java : call java");
|
||||||
@ -431,6 +600,13 @@ class AndroidContext : public ewol::Context {
|
|||||||
m_currentHeight = _size.y();
|
m_currentHeight = _size.y();
|
||||||
ewol::Context::OS_Resize(_size);
|
ewol::Context::OS_Resize(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audioPlayback(void* _dataOutput, int32_t _frameRate) {
|
||||||
|
if (m_audioCallBack != NULL) {
|
||||||
|
//EWOL_DEBUG("IO Audio event request: Frames=" << _frameRate);
|
||||||
|
m_audioCallBack(_dataOutput, _frameRate, m_audioCallBackUserData);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<AndroidContext*> s_listInstance;
|
static std::vector<AndroidContext*> s_listInstance;
|
||||||
@ -440,6 +616,7 @@ extern "C" {
|
|||||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _jvm, void* _reserved) {
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _jvm, void* _reserved) {
|
||||||
// get the java virtual machine handle ...
|
// get the java virtual machine handle ...
|
||||||
etk::AutoLockMutex myLock(g_interfaceMutex);
|
etk::AutoLockMutex myLock(g_interfaceMutex);
|
||||||
|
etk::AutoLockMutex myLock2(g_interfaceAudioMutex);
|
||||||
g_JavaVM = _jvm;
|
g_JavaVM = _jvm;
|
||||||
EWOL_DEBUG("JNI-> load the jvm ..." );
|
EWOL_DEBUG("JNI-> load the jvm ..." );
|
||||||
return JNI_VERSION_1_6;
|
return JNI_VERSION_1_6;
|
||||||
@ -447,6 +624,7 @@ extern "C" {
|
|||||||
// JNI onUnLoad
|
// JNI onUnLoad
|
||||||
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* _vm, void *_reserved) {
|
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* _vm, void *_reserved) {
|
||||||
etk::AutoLockMutex myLock(g_interfaceMutex);
|
etk::AutoLockMutex myLock(g_interfaceMutex);
|
||||||
|
etk::AutoLockMutex myLock2(g_interfaceAudioMutex);
|
||||||
g_JavaVM = NULL;
|
g_JavaVM = NULL;
|
||||||
EWOL_DEBUG("JNI-> Un-load the jvm ..." );
|
EWOL_DEBUG("JNI-> Un-load the jvm ..." );
|
||||||
}
|
}
|
||||||
@ -849,7 +1027,7 @@ extern "C" {
|
|||||||
s_listInstance[_id]->OS_Resize(vec2(_w, _h));
|
s_listInstance[_id]->OS_Resize(vec2(_w, _h));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Return tur or foalse to not redraw when the under draw has not be done (processing gain of time)
|
// TODO : Return true or false to not redraw when the under draw has not be done (processing gain of time)
|
||||||
void Java_org_ewol_Ewol_EWrenderDraw(JNIEnv* _env,
|
void Java_org_ewol_Ewol_EWrenderDraw(JNIEnv* _env,
|
||||||
jobject _thiz,
|
jobject _thiz,
|
||||||
jint _id) {
|
jint _id) {
|
||||||
@ -870,7 +1048,7 @@ extern "C" {
|
|||||||
jshortArray _location,
|
jshortArray _location,
|
||||||
jint _frameRate,
|
jint _frameRate,
|
||||||
jint _nbChannels) {
|
jint _nbChannels) {
|
||||||
etk::AutoLockMutex myLock(g_interfaceMutex);
|
etk::AutoLockMutex myLock(g_interfaceAudioMutex);
|
||||||
if( _id >= s_listInstance.size()
|
if( _id >= s_listInstance.size()
|
||||||
|| _id<0
|
|| _id<0
|
||||||
|| NULL == s_listInstance[_id] ) {
|
|| NULL == s_listInstance[_id] ) {
|
||||||
@ -882,9 +1060,10 @@ extern "C" {
|
|||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
jshort* dst = _env->GetShortArrayElements(_location, &isCopy);
|
||||||
if (NULL != dst) {
|
if (NULL != dst) {
|
||||||
//ewol::audio::getData(dst, _frameRate, _nbChannels);
|
memset(dst, sizeof(jshort), _frameRate*_nbChannels);
|
||||||
|
//EWOL_DEBUG("IO Audio event request: Frames=" << _frameRate << " channels=" << _nbChannels);
|
||||||
|
s_listInstance[_id]->audioPlayback(dst, _frameRate);
|
||||||
}
|
}
|
||||||
//APPL_DEBUG("IO Audio event request: Frames=" << frameRate << " channels=" << nbChannels);
|
|
||||||
// TODO : Understand why it did not work corectly ...
|
// TODO : Understand why it did not work corectly ...
|
||||||
//if (isCopy == JNI_TRUE) {
|
//if (isCopy == JNI_TRUE) {
|
||||||
// release the short* pointer
|
// release the short* pointer
|
||||||
|
@ -287,6 +287,30 @@ namespace ewol {
|
|||||||
* @return The curent time of the process
|
* @return The curent time of the process
|
||||||
*/
|
*/
|
||||||
static int64_t getTime(void);
|
static int64_t getTime(void);
|
||||||
|
#if defined(__TARGET_OS__Android)
|
||||||
|
public:
|
||||||
|
typedef void (*AndroidAudioCallback)(void* _data,
|
||||||
|
int32_t _size,
|
||||||
|
void* _userData);
|
||||||
|
// Android specific audio interface :
|
||||||
|
virtual int32_t audioGetDeviceCount(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual std::string audioGetDeviceProperty(int32_t _idDevice) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
virtual bool audioOpenDevice(int32_t _idDevice,
|
||||||
|
int32_t _freq,
|
||||||
|
int32_t _nbChannel,
|
||||||
|
int32_t _format,
|
||||||
|
AndroidAudioCallback _callback,
|
||||||
|
void* _userData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool audioCloseDevice(int32_t _idDevice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
// TODO : set user argument here ....
|
// TODO : set user argument here ....
|
||||||
|
|
||||||
|
@ -1,392 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <ewol/renderer/audio/audio.h>
|
|
||||||
#include <ewol/renderer/audio/decWav.h>
|
|
||||||
#include <ewol/debug.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
static int64_t currentTimePlaying = 0;
|
|
||||||
|
|
||||||
static bool musicMute = false;
|
|
||||||
static float musicVolume = 0;
|
|
||||||
static int32_t musicVolumeApply = 1<<16;
|
|
||||||
static int32_t musicFadingTime = 0;
|
|
||||||
|
|
||||||
static bool effectsMute = false;
|
|
||||||
static float effectsVolume = 0;
|
|
||||||
static int32_t effectsVolumeApply = 1<<16;
|
|
||||||
|
|
||||||
static bool isInit = false;
|
|
||||||
|
|
||||||
#ifdef BUILD_PORTAUDIO
|
|
||||||
# include <ewol/renderer/audio/interfacePortAudio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ewol::audio::init(void) {
|
|
||||||
if (isInit == true) {
|
|
||||||
EWOL_ERROR("multiple init requested ... at the audio system ...");
|
|
||||||
}
|
|
||||||
ewol::audio::effects::volumeSet(0);
|
|
||||||
ewol::audio::effects::muteSet(false);
|
|
||||||
ewol::audio::music::volumeSet(0);
|
|
||||||
ewol::audio::music::muteSet(false);
|
|
||||||
musicFadingTime = 100;
|
|
||||||
isInit = true;
|
|
||||||
#ifdef BUILD_PORTAUDIO
|
|
||||||
ewol::portAudio::init();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::unInit(void) {
|
|
||||||
if (false == isInit) {
|
|
||||||
EWOL_ERROR("multiple un-init requested ... at the audio system ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef BUILD_PORTAUDIO
|
|
||||||
ewol::portAudio::unInit();
|
|
||||||
#endif
|
|
||||||
musicMute = true;
|
|
||||||
musicVolume = -5000;
|
|
||||||
effectsMute = true;
|
|
||||||
effectsVolume = -5000;
|
|
||||||
musicFadingTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ewol::audio::AudioCallback userLocalCallback = NULL;
|
|
||||||
|
|
||||||
void ewol::audio::getData(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels) {
|
|
||||||
// TODO : set the real playing time ...
|
|
||||||
currentTimePlaying += 10;
|
|
||||||
if (_nbChannels != 2) {
|
|
||||||
EWOL_ERROR("TODO : Support the signal mono or more tha stereo ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// reset the current buffer
|
|
||||||
memset(_bufferInterlace, 0, _nbSample*sizeof(int16_t)*_nbChannels);
|
|
||||||
// get user data ...
|
|
||||||
if (NULL != userLocalCallback) {
|
|
||||||
(*userLocalCallback)(_bufferInterlace, _nbSample, _nbChannels);
|
|
||||||
}
|
|
||||||
// get background music :
|
|
||||||
ewol::audio::music::getData(_bufferInterlace, _nbSample, _nbChannels);
|
|
||||||
// add effects :
|
|
||||||
ewol::audio::effects::getData(_bufferInterlace, _nbSample, _nbChannels);
|
|
||||||
static FILE * plop = fopen("/home/edupin/testFile48khzstereo.raw", "w");
|
|
||||||
if (plop!=NULL) {
|
|
||||||
fwrite(_bufferInterlace, sizeof(int16_t), _nbSample*_nbChannels, plop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::addCallbackOutput(ewol::audio::AudioCallback _userCallback) {
|
|
||||||
userLocalCallback = _userCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ewol::audio::music::fading(int32_t _timeMs) {
|
|
||||||
musicFadingTime = _timeMs;
|
|
||||||
musicFadingTime = etk_avg(-100, musicFadingTime, 20);
|
|
||||||
EWOL_INFO("Set music fading time at " << _timeMs << "ms == > " << musicFadingTime << "ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listAdd(std::string _file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listRm(std::string _file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listClean(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listPrevious(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listNext(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listFirst(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listLast(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listPlay(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::listStop(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::play(std::string _file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::stop(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float ewol::audio::music::volumeGet(void) {
|
|
||||||
return musicVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uptateMusicVolume(void) {
|
|
||||||
if (musicMute == true) {
|
|
||||||
musicVolumeApply = 0;
|
|
||||||
} else {
|
|
||||||
// convert in an fixpoint value
|
|
||||||
// V2 = V1*10^(db/20)
|
|
||||||
double coef = pow(10, (musicVolume/20) );
|
|
||||||
musicVolumeApply = (int32_t)(coef * (double)(1<<16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ewol::audio::music::volumeSet(float _newVolume) {
|
|
||||||
musicVolume = _newVolume;
|
|
||||||
musicVolume = etk_avg(-1000, musicVolume, 40);
|
|
||||||
EWOL_INFO("Set music Volume at " << _newVolume << "dB == > " << musicVolume << "dB");
|
|
||||||
uptateMusicVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::music::muteGet(void) {
|
|
||||||
return musicMute;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::music::muteSet(bool _newMute) {
|
|
||||||
musicMute = _newMute;
|
|
||||||
EWOL_INFO("Set music Mute at " << _newMute);
|
|
||||||
uptateMusicVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::music::getData(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels) {
|
|
||||||
/*static int32_t maxValue = 0;
|
|
||||||
static float angle = 0;
|
|
||||||
maxValue +=10;
|
|
||||||
if (maxValue > 16000) {
|
|
||||||
maxValue = 0;
|
|
||||||
}
|
|
||||||
for (int iii = 0; iii<nbSample ; iii++) {
|
|
||||||
bufferInterlace[iii*2] = (float)maxValue * sin(angle/180.0 * M_PI);
|
|
||||||
bufferInterlace[iii*2+1] = bufferInterlace[iii*2];
|
|
||||||
angle+=0.9;
|
|
||||||
if (angle >= 360) {
|
|
||||||
angle -= 360.0;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
|
||||||
// Effects ...
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
|
||||||
//liste d'effet
|
|
||||||
class EffectsLoaded {
|
|
||||||
public :
|
|
||||||
EffectsLoaded(std::string _file)
|
|
||||||
{
|
|
||||||
m_file = _file;
|
|
||||||
m_requestedTime = 1;
|
|
||||||
m_data = ewol::audio::wav::loadData(_file, 1, 48000, m_nbSamples);
|
|
||||||
if (m_data == NULL) {
|
|
||||||
// write an error ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::string m_file;
|
|
||||||
int32_t m_nbSamples;
|
|
||||||
int32_t m_requestedTime;
|
|
||||||
int16_t* m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RequestPlay {
|
|
||||||
private:
|
|
||||||
bool m_freeSlot;
|
|
||||||
EffectsLoaded* m_effect; // reference to the effects
|
|
||||||
int32_t m_playTime; // position in sample playing in the audio effects
|
|
||||||
public :
|
|
||||||
RequestPlay(EffectsLoaded * _effect) : m_freeSlot(false), m_effect(_effect), m_playTime(0) { };
|
|
||||||
void reset(EffectsLoaded * _effect) { m_effect=_effect; m_playTime=0; m_freeSlot=false; };
|
|
||||||
bool isFree(void) { return m_freeSlot; };
|
|
||||||
void play(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels)
|
|
||||||
{
|
|
||||||
if (true == m_freeSlot) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_effect->m_data == NULL) {
|
|
||||||
m_freeSlot = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int32_t processTimeMax = etk_min(_nbSample, m_effect->m_nbSamples - m_playTime);
|
|
||||||
processTimeMax = etk_max(0, processTimeMax);
|
|
||||||
int16_t * pointer = _bufferInterlace;
|
|
||||||
int16_t * newData = &m_effect->m_data[m_playTime];
|
|
||||||
//EWOL_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " playTime=" <<m_playTime << " nbCannels=" << nbChannels);
|
|
||||||
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
|
||||||
// TODO : set volume and spacialisation ...
|
|
||||||
for (int32_t jjj=0; jjj<_nbChannels; jjj++) {
|
|
||||||
int32_t tmppp = *pointer + ((((int32_t)*newData)*effectsVolumeApply)>>16);
|
|
||||||
*pointer = etk_avg(-32767, tmppp, 32766);
|
|
||||||
//EWOL_DEBUG("AUDIO : element : " << *pointer);
|
|
||||||
pointer++;
|
|
||||||
}
|
|
||||||
newData++;
|
|
||||||
}
|
|
||||||
m_playTime += processTimeMax;
|
|
||||||
// check end of playing ...
|
|
||||||
if (m_effect->m_nbSamples <= m_playTime) {
|
|
||||||
m_freeSlot=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
std::vector<EffectsLoaded*> ListEffects;
|
|
||||||
std::vector<RequestPlay*> ListEffectsPlaying;
|
|
||||||
|
|
||||||
|
|
||||||
int32_t ewol::audio::effects::add(std::string _file) {
|
|
||||||
for (size_t iii=0; iii<ListEffects.size(); iii++) {
|
|
||||||
if (NULL != ListEffects[iii]) {
|
|
||||||
if (ListEffects[iii]->m_file == _file) {
|
|
||||||
ListEffects[iii]->m_requestedTime++;
|
|
||||||
return iii;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// effect does not exist ... create a new one ...
|
|
||||||
EffectsLoaded * tmpEffect = new EffectsLoaded(_file);
|
|
||||||
if (NULL == tmpEffect) {
|
|
||||||
EWOL_ERROR("Error to load the effects : \"" << _file << "\"");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ListEffects.push_back(tmpEffect);
|
|
||||||
return ListEffects.size()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::effects::rm(int32_t _effectId) {
|
|
||||||
// find element ...
|
|
||||||
if (_effectId <0 || _effectId >= (int64_t)ListEffects.size()) {
|
|
||||||
EWOL_ERROR("Wrong effect ID : " << _effectId << " != [0.." << ListEffects.size()-1 << "] == > can not remove it ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ListEffects[_effectId] == NULL) {
|
|
||||||
EWOL_ERROR("effect ID : " << _effectId << " == > has already been removed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check number of requested
|
|
||||||
if (ListEffects[_effectId]->m_requestedTime <= 0) {
|
|
||||||
EWOL_ERROR("effect ID : " << _effectId << " == > request more than predicted a removed of an effects");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ListEffects[_effectId]->m_requestedTime--;
|
|
||||||
// mark to be removed ... TODO : Really removed it when no other element readed it ...
|
|
||||||
// TODO : ...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::effects::play(int32_t _effectId, float _xxx, float _yyy) {
|
|
||||||
if (_effectId <0 || _effectId >= (int64_t)ListEffects.size()) {
|
|
||||||
EWOL_ERROR("Wrong effect ID : " << _effectId << " != [0.." << ListEffects.size()-1 << "] == > can not play it ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ListEffects[_effectId] == NULL) {
|
|
||||||
EWOL_ERROR("effect ID : " << _effectId << " == > has been removed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EWOL_VERBOSE("effect play : " << _effectId );
|
|
||||||
// try to find an empty slot :
|
|
||||||
for (size_t iii=0; iii<ListEffectsPlaying.size(); iii++) {
|
|
||||||
if (ListEffectsPlaying[iii]->isFree()) {
|
|
||||||
ListEffectsPlaying[iii]->reset(ListEffects[_effectId]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RequestPlay* newPlay = new RequestPlay(ListEffects[_effectId]);
|
|
||||||
if (NULL == newPlay) {
|
|
||||||
EWOL_CRITICAL("Allocation error of a playing element : " << _effectId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ListEffectsPlaying.push_back(newPlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float ewol::audio::effects::volumeGet(void) {
|
|
||||||
return effectsVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uptateEffectVolume(void) {
|
|
||||||
if (effectsMute == true) {
|
|
||||||
effectsVolumeApply = 0;
|
|
||||||
} else {
|
|
||||||
// convert in an fixpoint value
|
|
||||||
// V2 = V1*10^(db/20)
|
|
||||||
double coef = pow(10, (effectsVolume/20) );
|
|
||||||
effectsVolumeApply = (int32_t)(coef * (double)(1<<16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ewol::audio::effects::volumeSet(float _newVolume) {
|
|
||||||
effectsVolume = _newVolume;
|
|
||||||
effectsVolume = etk_avg(-100, effectsVolume, 20);
|
|
||||||
EWOL_INFO("Set music Volume at " << _newVolume << "dB == > " << effectsVolume << "dB");
|
|
||||||
uptateEffectVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ewol::audio::effects::muteGet(void) {
|
|
||||||
return effectsMute;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::effects::muteSet(bool _newMute) {
|
|
||||||
effectsMute = _newMute;
|
|
||||||
EWOL_INFO("Set effects Mute at " << _newMute);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ewol::audio::effects::getData(int16_t* _bufferInterlace, int32_t _nbSample, int32_t _nbChannels) {
|
|
||||||
for (size_t iii = 0; iii < ListEffectsPlaying.size(); ++iii) {
|
|
||||||
if (ListEffectsPlaying[iii]!= NULL) {
|
|
||||||
ListEffectsPlaying[iii]->play(_bufferInterlace, _nbSample, _nbChannels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __EWOL_AUDIO_H__
|
|
||||||
#define __EWOL_AUDIO_H__
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/types.h>
|
|
||||||
|
|
||||||
namespace ewol {
|
|
||||||
namespace audio {
|
|
||||||
void init(void);
|
|
||||||
void unInit(void);
|
|
||||||
|
|
||||||
typedef void (*AudioCallback)(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels);
|
|
||||||
void addCallbackOutput(AudioCallback _userCallback);
|
|
||||||
|
|
||||||
void getData(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels);
|
|
||||||
|
|
||||||
namespace music {
|
|
||||||
void fading(int32_t _timeMs);
|
|
||||||
// list playing system : is cyclic ...
|
|
||||||
bool listAdd(std::string _file);
|
|
||||||
bool listRm(std::string _file);
|
|
||||||
bool listClean(void);
|
|
||||||
bool listPrevious(void);
|
|
||||||
bool listNext(void);
|
|
||||||
bool listFirst(void);
|
|
||||||
bool listLast(void);
|
|
||||||
bool listPlay(void); // List playing
|
|
||||||
bool listStop(void); // List stopping
|
|
||||||
|
|
||||||
bool play(std::string _file); // play specific file ... pause the list element;
|
|
||||||
bool stop(void);
|
|
||||||
|
|
||||||
// in db
|
|
||||||
float volumeGet(void);
|
|
||||||
void volumeSet(float _newVolume);
|
|
||||||
bool muteGet(void);
|
|
||||||
void muteSet(bool _newMute);
|
|
||||||
void getData(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels);
|
|
||||||
|
|
||||||
};
|
|
||||||
// note effect is loaded in memory (then don't create long effect) and unload only when requested
|
|
||||||
namespace effects {
|
|
||||||
// note : support file (Mono, 16bit, 48kHz) : .raw or .wav (no encodage) or .ogg (decoded with tremor lib)
|
|
||||||
int32_t add(std::string _file);
|
|
||||||
void rm(int32_t _effectId);
|
|
||||||
void play(int32_t _effectId, float _xxx, float _yyy);
|
|
||||||
|
|
||||||
// in db
|
|
||||||
float volumeGet(void);
|
|
||||||
void volumeSet(float _newVolume);
|
|
||||||
bool muteGet(void);
|
|
||||||
void muteSet(bool _newMute);
|
|
||||||
void getData(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels);
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,294 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/os/FSNode.h>
|
|
||||||
#include <ewol/debug.h>
|
|
||||||
#include <ewol/renderer/audio/decWav.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char riffTag[4]; //!< 00-03
|
|
||||||
uint32_t size; //!< 04-07
|
|
||||||
char waveTag[4]; //!< 08-0b
|
|
||||||
char fmtTag[4]; //!< 0c-0f
|
|
||||||
uint32_t waveFormatSize; //!< 10-13
|
|
||||||
struct {
|
|
||||||
uint16_t type; //!< 00-01
|
|
||||||
uint16_t channelCount; //!< 02-03
|
|
||||||
uint32_t samplesPerSec; //!< 04-07
|
|
||||||
uint32_t bytesPerSec; //!< 08-0b
|
|
||||||
uint16_t bytesPerFrame; //!< 0c-0d
|
|
||||||
uint16_t bitsPerSample; //!< 0e-0f
|
|
||||||
}waveFormat; //!< 14-23
|
|
||||||
char dataTag[4]; //!< 24-27
|
|
||||||
uint32_t dataSize; //!< 28-2b
|
|
||||||
}waveHeader;
|
|
||||||
|
|
||||||
|
|
||||||
#define CONVERT_UINT32(littleEndien,data) (littleEndien)?(((uint32_t)((uint8_t*)data)[0] | (uint32_t)((uint8_t*)data)[1] << 8 | (uint32_t)((uint8_t*)data)[2] << 16 | (uint32_t)((uint8_t*)data)[3] << 24)): \
|
|
||||||
(((uint32_t)((uint8_t*)data)[3] | (uint32_t)((uint8_t*)data)[2] << 8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[0] << 24))
|
|
||||||
|
|
||||||
#define CONVERT_INT32(littleEndien,data) (littleEndien)?(((int32_t)((uint8_t*)data)[0] | (int32_t)((uint8_t*)data)[1] << 8 | (int32_t)((uint8_t*)data)[2] << 16 | (int32_t)((int8_t*)data)[3] << 24)): \
|
|
||||||
(((int32_t)((uint8_t*)data)[3] | (int32_t)((uint8_t*)data)[2] << 8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[0] << 24))
|
|
||||||
|
|
||||||
#define CONVERT_UINT24(littleEndien,data) (littleEndien)?(((uint32_t)((uint8_t*)data)[0]<<8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[2] << 24)): \
|
|
||||||
(((uint32_t)((uint8_t*)data)[2]<<8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[0] << 24))
|
|
||||||
|
|
||||||
#define CONVERT_INT24(littleEndien,data) (littleEndien)?(((int32_t)((uint8_t*)data)[0]<<8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[2] << 24)): \
|
|
||||||
(((int32_t)((uint8_t*)data)[2]<<8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[0] << 24))
|
|
||||||
|
|
||||||
#define CONVERT_UINT16(littleEndien,data) (littleEndien)?(((uint16_t)((uint8_t*)data)[0] | (uint16_t)((uint8_t*)data)[1] << 8)): \
|
|
||||||
(((uint16_t)((uint8_t*)data)[1] | (uint16_t)((uint8_t*)data)[0] << 8))
|
|
||||||
|
|
||||||
#define CONVERT_INT16(littleEndien,data) (littleEndien)?(((int16_t)((uint8_t*)data)[0] | (int16_t)((int8_t*)data)[1] << 8)): \
|
|
||||||
(((int16_t)((uint8_t*)data)[1] | (int16_t)((int8_t*)data)[0] << 8))
|
|
||||||
|
|
||||||
#define COMPR_PCM (1)
|
|
||||||
#define COMPR_MADPCM (2)
|
|
||||||
#define COMPR_ALAW (6)
|
|
||||||
#define COMPR_MULAW (7)
|
|
||||||
#define COMPR_ADPCM (17)
|
|
||||||
#define COMPR_YADPCM (20)
|
|
||||||
#define COMPR_GSM (49)
|
|
||||||
#define COMPR_G721 (64)
|
|
||||||
#define COMPR_MPEG (80)
|
|
||||||
|
|
||||||
int16_t * ewol::audio::wav::loadData(std::string filename, int8_t nbChan, int32_t frequency, int32_t & nbSampleOut) {
|
|
||||||
nbSampleOut = 0;
|
|
||||||
waveHeader myHeader;
|
|
||||||
memset(&myHeader, 0, sizeof(waveHeader));
|
|
||||||
etk::FSNode fileAccess(std::string("DATA:") + filename);
|
|
||||||
// Start loading the XML :
|
|
||||||
EWOL_DEBUG("open file (WAV) \"" << fileAccess << "\"");
|
|
||||||
|
|
||||||
if (false == fileAccess.exist()) {
|
|
||||||
EWOL_ERROR("File Does not exist : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
int32_t fileSize = fileAccess.fileSize();
|
|
||||||
if (0 == fileSize) {
|
|
||||||
EWOL_ERROR("This file is empty : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (false == fileAccess.fileOpenRead()) {
|
|
||||||
EWOL_ERROR("Can not open the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// try to find endienness :
|
|
||||||
if (fileSize < (int64_t)sizeof(waveHeader)) {
|
|
||||||
EWOL_ERROR("File : \"" << fileAccess << "\" == > has not enouth data inside might be minumum of " << (int32_t)(sizeof(waveHeader)));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// ----------------------------------------------
|
|
||||||
// read the header :
|
|
||||||
// ----------------------------------------------
|
|
||||||
if (fileAccess.fileRead(&myHeader.riffTag, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
bool littleEndien = false;
|
|
||||||
if( myHeader.riffTag[0] == 'R'
|
|
||||||
&& myHeader.riffTag[1] == 'I'
|
|
||||||
&& myHeader.riffTag[2] == 'F'
|
|
||||||
&& (myHeader.riffTag[3] == 'F' || myHeader.riffTag[3] == 'X') ) {
|
|
||||||
if (myHeader.riffTag[3] == 'F' ) {
|
|
||||||
littleEndien = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
EWOL_ERROR("file: \"" << fileAccess << "\" Does not start with \"RIF\" " );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// get the data size :
|
|
||||||
unsigned char tmpData[32];
|
|
||||||
if (fileAccess.fileRead(tmpData, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
myHeader.size = CONVERT_UINT32(littleEndien, tmpData);
|
|
||||||
|
|
||||||
// get the data size :
|
|
||||||
if (fileAccess.fileRead(&myHeader.waveTag, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if( myHeader.waveTag[0] != 'W'
|
|
||||||
|| myHeader.waveTag[1] != 'A'
|
|
||||||
|| myHeader.waveTag[2] != 'V'
|
|
||||||
|| myHeader.waveTag[3] != 'E' ) {
|
|
||||||
EWOL_ERROR("file: \"" << fileAccess << "\" This is not a wave file " << myHeader.waveTag[0] << myHeader.waveTag[1] << myHeader.waveTag[2] << myHeader.waveTag[3] );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the data size :
|
|
||||||
if (fileAccess.fileRead(&myHeader.fmtTag, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if( myHeader.fmtTag[0] != 'f'
|
|
||||||
|| myHeader.fmtTag[1] != 'm'
|
|
||||||
|| myHeader.fmtTag[2] != 't'
|
|
||||||
|| myHeader.fmtTag[3] != ' ' ) {
|
|
||||||
EWOL_ERROR("file: \"" << fileAccess << "\" header error ..." << myHeader.fmtTag[0] << myHeader.fmtTag[1] << myHeader.fmtTag[2] << myHeader.fmtTag[3]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// get the data size :
|
|
||||||
if (fileAccess.fileRead(tmpData, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
myHeader.waveFormatSize = CONVERT_UINT32(littleEndien, tmpData);
|
|
||||||
|
|
||||||
if (myHeader.waveFormatSize != 16) {
|
|
||||||
EWOL_ERROR("file : \"" << fileAccess << "\" == > header error ...");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (fileAccess.fileRead(tmpData, 1, 16)!=16) {
|
|
||||||
EWOL_ERROR("Can not 16 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
unsigned char * tmppp = tmpData;
|
|
||||||
myHeader.waveFormat.type = CONVERT_UINT16(littleEndien, tmppp);
|
|
||||||
tmppp += 2;
|
|
||||||
myHeader.waveFormat.channelCount = CONVERT_UINT16(littleEndien, tmppp);
|
|
||||||
tmppp += 2;
|
|
||||||
myHeader.waveFormat.samplesPerSec = CONVERT_UINT32(littleEndien, tmppp);
|
|
||||||
tmppp += 4;
|
|
||||||
myHeader.waveFormat.bytesPerSec = CONVERT_UINT32(littleEndien, tmppp);
|
|
||||||
tmppp += 4;
|
|
||||||
myHeader.waveFormat.bytesPerFrame = CONVERT_UINT16(littleEndien, tmppp);
|
|
||||||
tmppp += 2;
|
|
||||||
myHeader.waveFormat.bitsPerSample = CONVERT_UINT16(littleEndien, tmppp);
|
|
||||||
EWOL_DEBUG("audio properties : ");
|
|
||||||
EWOL_DEBUG(" type : " << myHeader.waveFormat.type);
|
|
||||||
EWOL_DEBUG(" channelCount : " << myHeader.waveFormat.channelCount);
|
|
||||||
EWOL_DEBUG(" samplesPerSec : " << myHeader.waveFormat.samplesPerSec);
|
|
||||||
EWOL_DEBUG(" bytesPerSec : " << myHeader.waveFormat.bytesPerSec);
|
|
||||||
EWOL_DEBUG(" bytesPerFrame : " << myHeader.waveFormat.bytesPerFrame);
|
|
||||||
EWOL_DEBUG(" bitsPerSample : " << myHeader.waveFormat.bitsPerSample);
|
|
||||||
// get the data size :
|
|
||||||
if (fileAccess.fileRead(&myHeader.dataTag, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if( myHeader.dataTag[0] != 'd'
|
|
||||||
|| myHeader.dataTag[1] != 'a'
|
|
||||||
|| myHeader.dataTag[2] != 't'
|
|
||||||
|| myHeader.dataTag[3] != 'a' ) {
|
|
||||||
EWOL_ERROR("file: \"" << fileAccess << "\" header error ..." << myHeader.dataTag[0] << myHeader.dataTag[1] << myHeader.dataTag[2] << myHeader.dataTag[3]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// get the data size :
|
|
||||||
if (fileAccess.fileRead(tmpData, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
myHeader.dataSize = CONVERT_UINT32(littleEndien, tmpData);
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
// end of the header reading done ...
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
//Parse the data and transform it if needed ...
|
|
||||||
if (COMPR_PCM != myHeader.waveFormat.type) {
|
|
||||||
EWOL_ERROR("File : \"" << fileAccess << "\" == > support only PCM compression ...");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (myHeader.waveFormat.channelCount == 0 || myHeader.waveFormat.channelCount>2) {
|
|
||||||
EWOL_ERROR("File : \"" << fileAccess << "\" == > support only mono or stereo ..." << myHeader.waveFormat.channelCount);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ( ! ( myHeader.waveFormat.bitsPerSample == 16
|
|
||||||
|| myHeader.waveFormat.bitsPerSample == 24
|
|
||||||
|| myHeader.waveFormat.bitsPerSample == 32 ) ) {
|
|
||||||
EWOL_ERROR("File : \"" << fileAccess << "\" == > not supported bit/sample ..." << myHeader.waveFormat.bitsPerSample);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if( ! ( 44100 == myHeader.waveFormat.samplesPerSec
|
|
||||||
|| 48000 == myHeader.waveFormat.samplesPerSec) ) {
|
|
||||||
EWOL_ERROR("File : \"" << fileAccess << "\" == > not supported frequency " << myHeader.waveFormat.samplesPerSec << " != 48000");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EWOL_DEBUG(" dataSize : " << myHeader.dataSize);
|
|
||||||
//int32_t globalDataSize = myHeader.dataSize;
|
|
||||||
int32_t nbSample = (myHeader.dataSize/((myHeader.waveFormat.bitsPerSample/8)*myHeader.waveFormat.channelCount));
|
|
||||||
int32_t outputSize = nbChan*nbSample;
|
|
||||||
int16_t * outputData = (int16_t*)malloc(outputSize*sizeof(int16_t));
|
|
||||||
if (NULL == outputData) {
|
|
||||||
EWOL_ERROR("Allocation ERROR try to allocate " << (int32_t)(outputSize*sizeof(int16_t) ) << "bytes");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
int16_t * tmpOut = outputData;
|
|
||||||
for( int32_t iii=0; iii<nbSample; iii++) {
|
|
||||||
int32_t left;
|
|
||||||
int32_t right;
|
|
||||||
char audioSample[8];
|
|
||||||
if (myHeader.waveFormat.bitsPerSample == 16) {
|
|
||||||
if (myHeader.waveFormat.channelCount == 1) {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 2)!=2) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = ((int32_t)((int16_t)CONVERT_INT16(littleEndien, audioSample))) << 16;
|
|
||||||
right = left;
|
|
||||||
} else {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = (int32_t)((int16_t)CONVERT_INT16(littleEndien, audioSample)) << 16;
|
|
||||||
right = (int32_t)((int16_t)CONVERT_INT16(littleEndien, audioSample+2)) << 16;
|
|
||||||
}
|
|
||||||
} else if (myHeader.waveFormat.bitsPerSample == 24) {
|
|
||||||
if (myHeader.waveFormat.channelCount == 1) {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 3)!=3) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = CONVERT_INT24(littleEndien, audioSample);
|
|
||||||
right = left;
|
|
||||||
} else {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 6)!=6) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = CONVERT_INT24(littleEndien, audioSample);
|
|
||||||
right = CONVERT_INT24(littleEndien, audioSample+3);
|
|
||||||
}
|
|
||||||
} else if (myHeader.waveFormat.bitsPerSample == 32) {
|
|
||||||
if (myHeader.waveFormat.channelCount == 1) {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 4)!=4) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = CONVERT_INT32(littleEndien, audioSample);
|
|
||||||
right = left;
|
|
||||||
} else {
|
|
||||||
if (fileAccess.fileRead(audioSample, 1, 8)!=8) {
|
|
||||||
EWOL_ERROR("Read Error at position : " << iii);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
left = CONVERT_INT32(littleEndien, audioSample);
|
|
||||||
right = CONVERT_INT32(littleEndien, audioSample+4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nbChan == 1) {
|
|
||||||
*tmpOut++ = (int16_t)(((left>>1) + (right>>1))>>16);
|
|
||||||
} else {
|
|
||||||
*tmpOut++ = (int16_t)(left>>16);
|
|
||||||
*tmpOut++ = (int16_t)(left>>16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close the file:
|
|
||||||
fileAccess.fileClose();
|
|
||||||
nbSampleOut = nbSample;
|
|
||||||
return outputData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __EWOL_AUDIO_DEC_WAV_H__
|
|
||||||
#define __EWOL_AUDIO_DEC_WAV_H__
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/types.h>
|
|
||||||
|
|
||||||
namespace ewol {
|
|
||||||
namespace audio {
|
|
||||||
namespace wav {
|
|
||||||
int16_t * loadData(std::string filename, int8_t nbChan, int32_t frequency, int32_t & nbSampleOut);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <etk/types.h>
|
|
||||||
#include <ewol/debug.h>
|
|
||||||
#include <ewol/renderer/audio/interfacePortAudio.h>
|
|
||||||
#include <ewol/renderer/audio/audio.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <math.h>
|
|
||||||
extern "C" {
|
|
||||||
#include <portaudio/portaudio.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t sampleRate;
|
|
||||||
int32_t nbChanelsInput;
|
|
||||||
int32_t nbChanelsOutput;
|
|
||||||
int32_t frameSize;
|
|
||||||
} userOutputData;
|
|
||||||
|
|
||||||
userOutputData data;
|
|
||||||
PaStream *stream;
|
|
||||||
|
|
||||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
|
||||||
It may called at interrupt level on some machines so don't do anything
|
|
||||||
that could mess up the system like calling malloc() or free().
|
|
||||||
*/
|
|
||||||
static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
|
||||||
unsigned long framesPerBuffer,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags,
|
|
||||||
void *userData ) {
|
|
||||||
/* Cast data passed through stream to our structure. */
|
|
||||||
userOutputData *data = (userOutputData*)userData;
|
|
||||||
// no use of the input buffer ... (mightt be NULL)
|
|
||||||
(void) inputBuffer;
|
|
||||||
ewol::audio::getData((int16_t*)outputBuffer, framesPerBuffer, data->nbChanelsOutput);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SAMPLE_RATE (44100)
|
|
||||||
|
|
||||||
void ewol::portAudio::init(void) {
|
|
||||||
PaError err;
|
|
||||||
EWOL_DEBUG("Create Audio Thread...");
|
|
||||||
|
|
||||||
err = Pa_Initialize();
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data.sampleRate = 48000;
|
|
||||||
data.nbChanelsInput = 0;
|
|
||||||
data.nbChanelsOutput = 2;
|
|
||||||
data.frameSize = 256;
|
|
||||||
/* open an audio I/O stream. */
|
|
||||||
err = Pa_OpenDefaultStream( &stream, data.nbChanelsInput, data.nbChanelsOutput,
|
|
||||||
paInt16, data.sampleRate, data.frameSize,
|
|
||||||
patestCallback, &data );
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = Pa_StartStream( stream );
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EWOL_DEBUG("Create Audio Thread ... might have start");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ewol::portAudio::unInit(void) {
|
|
||||||
PaError err;
|
|
||||||
// destroy the thread ...
|
|
||||||
EWOL_DEBUG("Wait end of the thread ...");
|
|
||||||
err = Pa_StopStream( stream );
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = Pa_CloseStream( stream );
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = Pa_Terminate();
|
|
||||||
if( err != paNoError ) {
|
|
||||||
EWOL_ERROR("PortAudio error: " << (char*)Pa_GetErrorText(err) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EWOL_DEBUG("Create Audio Thread ... might have stop");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
*
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
*
|
|
||||||
* @license BSD v3 (see license file)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __EWOL_PORT_AUDIO_H__
|
|
||||||
#define __EWOL_PORT_AUDIO_H__
|
|
||||||
|
|
||||||
#include <etk/types.h>
|
|
||||||
|
|
||||||
namespace ewol {
|
|
||||||
namespace portAudio {
|
|
||||||
void init(void);
|
|
||||||
void unInit(void);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
x
Reference in New Issue
Block a user