質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • Java

    16163questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • C

    4659questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4526questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • DLL

    111questions

    DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

JavaでJNAを用いてOGGを同時に再生できない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,523

KureteRubyLua

score 186

JavaでJNAを用いてDLL上でOGGをデコードし、Java上で再生するという事をやっているのですが、マルチスレッドを用いて同時に再生しようとすると、何故かInvalid Memory Accessが出たり、音がおかしくなったりします。原因は全く分かりません。

ソースコードは以下の通りです。OGGのデコードのソースは以下のURLを使用しております。

http://marupeke296.com/OGG_main.html

よろしくお願いします。

DLL部分

#include <memory.h>
#include <string>
#include <iostream>
#include "vorbis/vorbisfile.h"
#include "OggDecoder.h"
#include "OggVorbisMemory.h"
#include "OggVorbisFile.h"
#include "PCMPlayer.h"
#include "DixSmartPtr.h"
#include "DixComPtr.h"
#include "OggMain.h"

using namespace std;

Dix::sp< Dix::OggVorbisMemory > spOggResource;
Dix::sp< Dix::OggDecoder > spOggDecoder;
int check;
char* path;

extern "C" int OggDll::open(char* filePath)
{
    check = -1;
    path = filePath;

    spOggResource = Dix::sp< Dix::OggVorbisMemory > (new Dix::OggVorbisMemory);
    if (spOggResource->createBuffer(filePath) == false)
    {
        check = -1;
        return -1;
    }
    else
    {
        check = 0;
        spOggDecoder = Dix::sp< Dix::OggDecoder>(new Dix::OggDecoder(spOggResource));
        spOggDecoder->getSampleRate();
        return 0;
    }
}

extern "C" void OggDll::close()
{
}


// 指定サイズでPCM音声バッファを埋める関数
extern "C" int OggDll::getPCMBuffer(char* buffer,int bufferSize)
{
    bool a = true;
    unsigned int b = 100;
    if(check==-1)
    {
        return -1;
    }
    else
    {
        spOggDecoder->getSegment(buffer, bufferSize, &b, &a);
        if (a == true)
        {
            cout << " a true " << endl;
            return 0;
        }
        else
        {
            cout << " a  false" << endl;
            return -1;
        }
    }
}

// 指定サイズでPCM音声バッファを埋める関数
extern "C" int OggDll::getSampleRate()
{
    if (check == -1)
    {
        return -1;
    }
    else
    {
        return spOggDecoder->getSampleRate();
    }
}

// 指定サイズでPCM音声バッファを埋める関数
extern "C" int OggDll::getChannel()
{
    if (check == -1)
    {
        return -1;
    }
    else
    {
        return spOggDecoder->getChannel();
    }
}


Java

public interface OggDllLibrary extends Library {
    public String JNA_LIBRARY_NAME = "OggDll";
    public NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(OggDllLibrary.JNA_LIBRARY_NAME);
    public OggDllLibrary INSTANCE = (OggDllLibrary)Native.loadLibrary(OggDllLibrary.JNA_LIBRARY_NAME, OggDllLibrary.class);
    int getPCMBuffer(ByteBuffer buffer, int bufferSize);
    int open(String filePath);
    int close();
    int getSampleRate();
    int getChannel();
}

public class OggClip extends DataClip {
    //Oggを再生するためのDLLを呼び出す変数
    OggDllLibrary oggDll;
    //バッファ
    ByteBuffer buffer;
    /**
     * コンストラクタ
     * @param file ファイル
     * @param volume ボリューム
     * @param intPitch ピッチ(50~150%)
     * @param leftRight 左右の位相
     * @throws UnsupportedAudioFileException
     * @throws IOException
     * @throws LineUnavailableException
     */
    public OggClip(File file, int volume, int intPitch, int leftRight)
            throws UnsupportedAudioFileException, IOException,
            LineUnavailableException {
        super(file, volume, intPitch, leftRight);
        oggDll=(OggDllLibrary)Native.loadLibrary(OggDllLibrary.JNA_LIBRARY_NAME, OggDllLibrary.class);

        oggDll.open(file.getAbsolutePath());
        AudioFormat format = new AudioFormat(oggDll.getSampleRate(), 16,oggDll.getChannel(), true, false);
        DataLine.Info info = new DataLine.Info (SourceDataLine.class,format, AudioSystem.NOT_SPECIFIED); 
        // ラインを取得
        line = (SourceDataLine) AudioSystem.getLine (info);
        bits=16;
        buffer=ByteBuffer.allocate(oggDll.getSampleRate());
        sampleRate=oggDll.getSampleRate();
        line.open(format);
        thread.start();
    }

    /**
     * 実際に再生する
     */
    public void render() throws IOException {
        int ret;
        if (playing) {
            ret = oggDll.getPCMBuffer(buffer,sampleRate);
            System.out.println(file.getAbsolutePath()+" "+ret);
            if(ret != -1)
            {
                //データを加工する
                processingByteData=resampling(buffer.array());
                line.write (processingByteData, 0, processingByteData.length);
            }
            else
            {
                notYetEOF= false;
            }
        } else { 
            try { Thread.sleep (10);} 
            catch (InterruptedException ie) {}
        }
    }

    /**
     * スタート
     */
    public void start() {
        playing = true;
        line.start();
    }
    /**
     * 再スタート
     */
    public void contStart(){
        if(playing){
            oggDll.open(file.getAbsolutePath());
            super.contStart();
        }else{
            start();
        }
    }

    /**
     * ストップ
     */
    public void stop(){
        super.stop();
        oggDll.close();
    }


    /**
     * スレッド上で稼働させる関数
     */
    public void run()
    {
        try {
            while(true)
            {
               System.out.println("playing "+playing +" notYetEOF "+notYetEOF);
               if(playing && notYetEOF)
               {
                  render();
               }
               else
               {
                   stop();

                   break;
               }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

これはおそらく、
DLL側がマルチスレッドに対応していないためではないでしょうか。

Dix::sp< Dix::OggVorbisMemory > spOggResourceを含めて4つのグローバル変数を2つのスレッドで共有してしまっているんだと思います。

JNAは詳しくないので具体的な対応方法はお教えすることができませんが、
変数を構造体にまとめるかクラス化するかして、スレッドごとにインスタンスを作るようにすれば回避できるかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/26 21:39 編集

    >変数を構造体にまとめるかクラス化するかして、スレッドごとにインスタンスを作るようにすれば回避できるかもしれません。
    これを行うには具体的にどのようにすればいいのでしょうか?

    キャンセル

  • 2016/05/26 22:01

    回答に書いた通り、具体的にどうすれば良いのか適切にお教えすることができません。

    私の推測では、この質問がJNAに特化しているため、C++に詳しい回答者さんに見てもらえていない可能性があると思っています。
    「DLLのマルチスレッド対応」という切り口で別途質問されてみては如何ですか?

    私はJava+JNAに限らず、他言語からマルチスレッドでこのDLLを呼び出した場合に同様の問題が発生するかも知れないと思っていますので、
    質問のポイントとしては、

    ・この質問に関連する質問であることを明記してください。(この質問のURLを貼ってください)
    ・タイトルとタグは、Javaについて触れないでおいてください。
    ・本文で、JavaからJNA経由でマルチスレッドで呼び出している旨を書いてください。

    この辺を押さえてやってみてください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    16163questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • C

    4659questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4526questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • DLL

    111questions

    DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。