だから、私は概念的な疑問を持っています。私は低レベルのオーディオを作る目的でAndroid上のJNIと仕事をしてきました。私はC/C++でたくさんのオーディオコーディングを行ったので、これはあまり問題ではないと考えました。私は自分の「ネイティブ」コードでC++を使うことにしました(誰がOOPを愛していないのですか?)。私が遭遇した問題は、奇妙な一つであることが(私には)そうです:私はC++コードでオーディオを処理するためのオブジェクトを作成し、ときに私は、この上のメソッドを呼び出す、Javaへのこのオブジェクト(またその逆)を渡すことはありませんオブジェクトはガベージコレクションをかなり頻繁に呼び出すようです。これは、音声コールバックの内部に起こっているので、結果は吃音オーディオであり、そしてIは、線に沿って頻繁にメッセージ得る:私は静的関数を作成する(というよりも上のメンバメソッドを呼び出すことによって、同じ操作を実行すると、しかしAndroid JNIネイティブコードのC++オブジェクトはガベージコレクションを呼び出しますか?
WAIT_FOR_CONCURRENT_GC blocked 23ms
をmemeberオブジェクト)は、アプリケーションのパフォーマンスは良いと思われ、私はもはや上記のログメッセージが表示されます。基本的には
、ネイティブコード内のメンバーオブジェクトのメンバメソッドを呼び出すよりも優れた性能を持っている必要があり、静的な関数を呼び出す何らかの理由があるのでしょうか?は具体的には、メンバーオブジェクト、またはガベージコレクションに関与JNIプロジェクトのネイティブコード内で完全に住んで限られた範囲変数ですか? C++コールスタックはGCに含まれていますか? JNIプログラミングに関して、C++メモリ管理がJavaメモリ管理とどのように合致するかについて、誰かが私に与える洞察はありますか?つまり、JavaとC++の間でデータを渡さない場合、C++コードを書く方法はJavaメモリ管理(GCなど)に影響しますか?
私は例を与えることを試みることを許可します。あなたが洞察力を持っていると思うなら、ここで読むのをやめるのは大歓迎です。
私は、オブジェクトのカップルを持っています。オーディオエンジンの作成、出力の初期化などを担当するもの。これはHelloAudioJNIと呼ばれています(コンパイル可能なサンプルを置いていないのは申し訳ありませんが、コードがたくさんあります)。
class CHelloAudioJNI {
... omitted members ...
//member object pointers
COscillator *osc;
CWaveShaper *waveShaper;
... etc ...
public:
//some methods
void init(float fs, int bufferSize, int channels);
... blah blah blah ...
私にはさらに2つのクラスがあります。ウェーブシェイパークラスには、次のようになります。
class CWaveShaper : public CAudioFilter {
protected:
double *coeffs;
unsigned int order;//order
public:
CWaveShaper(const double sampleRate, const unsigned int numChannels,
double *coefficients, const unsigned int order);
double processSample(double input, unsigned int channel);
void reset();
};
は、この例では、すでにかなり長いためのが、今のところCAudioFilterクラス心配ないようにしましょう。 WaveShaperの.cppファイルは次のようになります。
CWaveShaper::CWaveShaper(const double sampleRate,
const unsigned int numChannels,
double *coefficients,
const unsigned int numCoeffs) :
CAudioFilter(sampleRate,numChannels), coeffs(coefficients), order(numCoeffs)
{}
double CWaveShaper::processSample(double input, unsigned int channel)
{
double output = 0;
double pow = input;
//zeroth order polynomial:
output = pow * coeffs[0];
//each additional iteration
for(int iteration = 1; iteration < order; iteration++){
pow *= input;
output += pow * coeffs[iteration];
}
return output;
}
void CWaveShaper::reset() {}
次にHelloAudioJNI.cppがあります。これが問題の肉体に入り込む場所です。
void CHelloAudioJNI::init(float samplerate, int bufferSize, int channels)
{
... some omitted initialization code ...
//wave shaper numero uno
double coefficients[2] = {1.0/2.0, 3.0/2.0};
waveShaper = new CWaveShaper(fs,outChannels,coefficients,2);
... some more omitted code ...
}
[OK]を、すべてがこれまでの罰金だ:私はメンバーは以下のようなものを、init関数内で新しいを使用して、適切にオブジェクトを作成します。そして、オーディオコールバックの内側に、私たちはそうのようなメンバオブジェクトにいくつかのメンバー・メソッドを呼び出します。
void CHelloAudioJNI::processOutputBuffer()
{
//compute audio using COscillator object
for(int index = 0; index < outputBuffer.bufferLen; index++){
for(int channel = 0; channel < outputBuffer.numChannels; channel++){
double sample;
//synthesize
sample = osc->computeSample(channel);
//wave-shape
sample = waveShaper->processSample(sample,channel);
//convert to FXP and save to output buffer
short int outputSample = amplitude * sample * FLOAT_TO_SHORT;
outputBuffer.buffer[interleaveIndex(index,channel)] = outputSample;
}
}
}
これは頻繁に音声途切れやガベージコレクションに関するメッセージの多くを生成するものです。しかし、私はすぐにコールバックの上HelloAudioJNI.cppにCWaveShaper :: processSample()関数をコピーして代わりに、直接のメンバ関数を呼び出す場合:
sample = waveShape(sample, coeff, 2);
は、その後、私は私のアンドロイドから出てくる美しい美しいオーディオを取得します私はガーベッジコレクションについてのこのような頻繁なメッセージを受け取っていません。もう一度質問があり、は、メンバーオブジェクト、またはガベージコレクションに関与JNIプロジェクトのネイティブコード内で完全に住んで限られた範囲変数ですか? C++コールスタックはGCに含まれていますか? JNIプログラミングに関して、C++メモリ管理がJavaメモリ管理とどのように合致するかについて、誰かが私に与える洞察はありますか?つまり、JavaとC++の間でデータを渡さない場合、C++コードを書く方法はJavaメモリ管理(GCなど)に影響しますか?
これは接線である可能性があります。係数は読み込まれるが書き込まれないもののように聞こえるからです。したがって、アクセスされたときの値は不確定な可能性がありますが、スタックの破損が発生することはすぐには分かりません。 –
@ChrisStratton、あなたのコメントを説明できますか?私はあなたが意味することを理解していません。 – xaviersjs
ここで提起問題はもはや割り当てられたメモリからアクセス係数の値が不正確である可能性が高いとあなたが解決しなければならないものです。しかし、あとで係数を変更しようとしない限り、これは不適切なプログラムフローを引き起こすことはありません。これは、この答えによって暗黙的に提供されるガベージコレクションの唯一の説明のようです。すべての入力に対して有効な計算に使用する係数のみを*読み込んだ場合、「BadThings(tm)」は「間違った計算結果」に限定されます。 –