■□MIDIDataライブラリについて質問です□■

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kero_nao

■□MIDIDataライブラリについて質問です□■

#1

投稿記事 by kero_nao » 7年前


MIDIDataライブラリとは、MIDIデータ作成・編集用のライブラリなのですが、トラックの追加がうまくいかず困っております。
以下のページからMIDIIDataライブラリとそのガイドブックがDLいただけます。
おーぷんMIDIぷろじぇくと

何処が間違っているのかご指導いただけませんか?



以下がソースコードとなります。
Track1はピアノのメロディで、Track2がギターの伴奏なのですが、トラックや音色の振り分けが上手くいっていないようです。。

コード:

#include <stdio.h>
#include <MIDIData.h>
int main() {

	MIDIData* pMIDIData;
	MIDITrack* pMIDITrack1;

	/* MIDIデータの生成(フォーマット1,トラック数2,TPQNベース,120) */
	pMIDIData = MIDIData_Create(MIDIDATA_FORMAT0, 2, MIDIDATA_TPQNBASE, 120);

	/* 最初のトラックへのポインタを取得 */
	pMIDITrack1 = MIDIData_GetFirstTrack(pMIDIData);

	/* メロディのイベントを挿入 */
	MIDITrack_InsertTrackName(pMIDITrack1, 0, "メロディ"); /* タイトル */
	MIDITrack_InsertTempo(pMIDITrack1, 0, 60000000 / 120); /* 120BPM */
	MIDITrack_InsertProgramChange(pMIDITrack1, 0, 0, 2); /* Piano */
	
   /* メロディのノートイベントを挿入*/
	MIDITrack_InsertNote(pMIDITrack1, 0, 0, 60, 100, 120); /* ど */
	MIDITrack_InsertNote(pMIDITrack1, 120, 0, 64, 100, 120); /* み */
	MIDITrack_InsertNote(pMIDITrack1, 240, 0, 67, 100, 120); /* そ */
	MIDITrack_InsertNote(pMIDITrack1, 360, 0, 60, 100, 120); /* ど */

	/* エンドオブトラックイベントを挿入 */
	MIDITrack_InsertEndofTrack(pMIDITrack1, 500);

	/*--------------------------------------------------------------------*/

	MIDITrack* pMIDITrack2 = MIDITrack_Create();

	pMIDITrack2 = MIDIData_GetFirstTrack(pMIDIData);

	/* 伴奏のイベントを挿入 */
	MIDITrack_InsertTrackName(pMIDITrack2, 0, "伴奏"); /* タイトル */
	MIDITrack_InsertTempo(pMIDITrack2, 0, 60000000 / 120); /* 120BPM */
	MIDITrack_InsertProgramChange(pMIDITrack2, 0, 0, 26); /* Guitar */

	/* 伴奏のノートイベントを挿入*/
	MIDITrack_InsertNote(pMIDITrack1, 0, 0, 60, 50, 480); /* ど */
	MIDITrack_InsertNote(pMIDITrack1, 0, 0, 64, 50, 480); /* み */
	MIDITrack_InsertNote(pMIDITrack1, 0, 0, 67, 50, 480); /* そ */
	MIDITrack_InsertNote(pMIDITrack1, 0, 0, 71, 50, 480); /* し */


	 /* エンドオブトラックイベントを挿入 */
	MIDITrack_InsertEndofTrack(pMIDITrack2, 500);

	/*メロディの後に伴奏を挿入*/
	MIDIData_InsertTrackAfter(pMIDIData, pMIDITrack2, pMIDITrack1);

	/* MIDIデータを保存 */
	MIDIData_SaveAsSMF(pMIDIData, L"C:メロディ&伴奏.mid");

	/* MIDIデータをメモリ上から削除 */
	MIDIData_Delete(pMIDIData);
	pMIDIData = NULL;
	return 1;
}

あんどーなつ
記事: 171
登録日時: 7年前
連絡を取る:

Re: ■□MIDIDataライブラリについて質問です□■

#2

投稿記事 by あんどーなつ » 7年前

Lがついている文字列とついていない文字列がありますが、混在はOKですか?
Visual Studioのプロジェクトのプロパティページで、
[構成プロパティ]-[全般]-[文字セット]で、[Unicode文字セットを使用する]に設定している場合はすべての文字列にLをつけてみてください。
マルチバイト文字を設定している場合はLをはずしてみてください。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: ■□MIDIDataライブラリについて質問です□■

#3

投稿記事 by みけCAT » 7年前

kero_nao さんが書きました:

コード:

	/* MIDIデータの生成(フォーマット1,トラック数2,TPQNベース,120) */
	pMIDIData = MIDIData_Create(MIDIDATA_FORMAT0, 2, MIDIDATA_TPQNBASE, 120);
スマホからなのでドキュメントは読んでいませんが、
フォーマット1を指定する識別子としてMIDIDATA_FORMAT0を使うのは正しいのですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ■□MIDIDataライブラリについて質問です□■

#4

投稿記事 by ISLe » 7年前

ドキュメントを読む限りはこんな感じでしょうか。
※コンパイル及び動作確認してません。

コード:

#include <stdio.h>
#include <MIDIData.h>
int main(void)
{

    MIDIData* pMIDIData;
    MIDITrack* pMIDITrack;

    /* MIDIデータの生成(フォーマット1,トラック数3,TPQNベース,120) */
    pMIDIData = MIDIData_Create(MIDIDATA_FORMAT1, 3, MIDIDATA_TPQNBASE, 120);

    /*--------------------------------------------------------------------*/

    /* 最初のトラックへのポインタを取得 */
    pMIDITrack = MIDIData_GetFirstTrack(pMIDIData);

    /* イベントを挿入 */
    MIDITrack_InsertTrackName(pMIDITrack, 0, _T("コンダクター")); /* タイトル */
    MIDITrack_InsertTempo(pMIDITrack, 0, 60000000 / 120); /* 120BPM */
 
     /* エンドオブトラックイベントを挿入 */
    MIDITrack_InsertEndofTrack(pMIDITrack, 500);

    /*--------------------------------------------------------------------*/

    /* 次のトラックへのポインタを取得 */
    pMIDITrack = MIDIData_GetNextTrack(pMIDITrack);

    /* メロディのイベントを挿入 */
    MIDITrack_InsertTrackName(pMIDITrack, 0, _T("メロディ")); /* タイトル */
    MIDITrack_InsertProgramChange(pMIDITrack, 0, 0, 2); /* Piano */
    
   /* メロディのノートイベントを挿入*/
    MIDITrack_InsertNote(pMIDITrack, 0, 0, 60, 100, 120); /* ど */
    MIDITrack_InsertNote(pMIDITrack, 120, 0, 64, 100, 120); /* み */
    MIDITrack_InsertNote(pMIDITrack, 240, 0, 67, 100, 120); /* そ */
    MIDITrack_InsertNote(pMIDITrack, 360, 0, 60, 100, 120); /* ど */
 
    /* エンドオブトラックイベントを挿入 */
    MIDITrack_InsertEndofTrack(pMIDITrack, 500);
 
    /*--------------------------------------------------------------------*/

    /* 次のトラックへのポインタを取得 */
    pMIDITrack = MIDIData_GetNextTrack(pMIDITrack);
 
    /* 伴奏のイベントを挿入 */
    MIDITrack_InsertTrackName(pMIDITrack, 0, _T("伴奏")); /* タイトル */
    MIDITrack_InsertProgramChange(pMIDITrack, 0, 0, 26); /* Guitar */
 
    /* 伴奏のノートイベントを挿入*/
    MIDITrack_InsertNote(pMIDITrack, 0, 0, 60, 50, 480); /* ど */
    MIDITrack_InsertNote(pMIDITrack, 0, 0, 64, 50, 480); /* み */
    MIDITrack_InsertNote(pMIDITrack, 0, 0, 67, 50, 480); /* そ */
    MIDITrack_InsertNote(pMIDITrack, 0, 0, 71, 50, 480); /* し */
 
     /* エンドオブトラックイベントを挿入 */
    MIDITrack_InsertEndofTrack(pMIDITrack, 500);
 
    /*--------------------------------------------------------------------*/

    /* MIDIデータを保存 */
    MIDIData_SaveAsSMF(pMIDIData, _T("C:メロディ&伴奏.mid"));
 
    /* MIDIデータをメモリ上から削除 */
    MIDIData_Delete(pMIDIData);
    pMIDIData = NULL;

    return 0;
}
・フォーマット指定の識別子を変更
・フォーマット1の最初のトラックはコンダクタートラックなのでそこでテンポ(だけ)を指定
・必要なトラックは最初に作成済みなので、次のトラックを取得する関数で切り替え

kero_nao

Re: ■□MIDIDataライブラリについて質問です□■

#5

投稿記事 by kero_nao » 7年前

たくさんのアドバイスありがとうございます!

>あんどーなつさん
文字のバイト数に関して間違ったところがありました。
ご指摘ありがとうございます。

>みけCATさん
MIDIDATA_FORMAT0→MIDIDATA_FORMAT1の間違いでした。
ご指摘ありがとうございます。

>ISLeさん
コードまで書いてくださって、ありがとうございます!
大変参考になります。

コンパイル時に見つかったエラー箇所を変更いたしました。

コード:

MIDIData_GetNextTrack(pMIDITrack);
Line:27,45について、Next→Last、pMIDITrack→pMIDIDataへ変更

コード:

MIDIData_GetLastTrac(pMIDIData);
肝心の動作ですが、ファイルは出力されるものの、
どんなソフトで読み込んでも、うまく再生されませんでした。。
現在、原因を解明中です。。

引き続き、ご指導・ご助言等、お待ちしております。

Tepp
記事: 13
登録日時: 7年前
住所: フォッサマグナ
連絡を取る:

Re: ■□MIDIDataライブラリについて質問です□■

#6

投稿記事 by Tepp » 7年前

kero_naoさんのエラーの直し方ではISLeさんのコード意図と違うものになってしまいます。
次のトラックを取りたいのに、最後のトラックを取ってはだめです。

さて、面白そうなので、調べて音が出るまでやってみました。
といっても、
ISLe さんが書きました: ・フォーマット指定の識別子を変更
・フォーマット1の最初のトラックはコンダクタートラックなのでそこでテンポ(だけ)を指定
・必要なトラックは最初に作成済みなので、次のトラックを取得する関数で切り替え
で、音はなります。
あとは、楽器がトラックごとに違うのでチャンネルも別々にしないと
音が混ざって正しい楽器でなってくれません。

以下、最終コード
(確認のため、出力先変更、伴奏の音量を小さくして、時間を長くしています)

コード:

#include <stdio.h>
#include <MIDIData.h>
int main() {

	MIDIData* pMIDIData = 0;
	MIDITrack* pMIDITrack0 = 0;
	MIDITrack* pMIDITrack1 = 0;
	MIDITrack* pMIDITrack2 = 0;

	/* MIDIデータの生成(フォーマット1,トラック数2,TPQNベース,120) */
	pMIDIData = MIDIData_Create(MIDIDATA_FORMAT1, 3, MIDIDATA_TPQNBASE, 120);

	/*--------------------------------------------------------------------*/
	/* トラック0 */
	pMIDITrack0 = MIDIData_GetFirstTrack(pMIDIData);
	MIDITrack_InsertTrackName(pMIDITrack0, 0, L"コンダクタートラック"); /* タイトル */
	MIDITrack_InsertTempo(pMIDITrack0, 0, 60000000 / 120); /* 120BPM */

	/* エンドオブトラックイベントを挿入 */
	MIDITrack_InsertEndofTrack(pMIDITrack0, 500);

	/*--------------------------------------------------------------------*/
	/*トラック1 */
	pMIDITrack1 = MIDITrack_GetNextTrack(pMIDITrack0);

	/* メロディのイベントを挿入 */
	MIDITrack_InsertTrackName(pMIDITrack1, 0, L"メロディ"); /* タイトル */
	MIDITrack_InsertTempo(pMIDITrack1, 0, 60000000 / 120); /* 120BPM */
	MIDITrack_InsertProgramChange(pMIDITrack1, 0, 0, 2); /* Piano */

	/* メロディのノートイベントを挿入*/
	MIDITrack_InsertNote(pMIDITrack1,   0, 0, 60, 100, 120); /* ど */
	MIDITrack_InsertNote(pMIDITrack1, 120, 0, 64, 100, 120); /* み */
	MIDITrack_InsertNote(pMIDITrack1, 240, 0, 67, 100, 120); /* そ */
	MIDITrack_InsertNote(pMIDITrack1, 360, 0, 60, 100, 120); /* ど */

	/* エンドオブトラックイベントを挿入 */
	MIDITrack_InsertEndofTrack(pMIDITrack1, 500);

	/*--------------------------------------------------------------------*/
	/*トラック2 */
	pMIDITrack2 = MIDITrack_GetNextTrack(pMIDITrack1);

	/* 伴奏のイベントを挿入 */
	MIDITrack_InsertTrackName(pMIDITrack2, 0, L"伴奏"); /* タイトル */
	MIDITrack_InsertTempo(pMIDITrack2, 0, 60000000 / 120); /* 120BPM */
	MIDITrack_InsertProgramChange(pMIDITrack2, 0, 1, 26); /* Guitar */

	/* 伴奏(和音)のノートイベントを挿入*/
	MIDITrack_InsertNote(pMIDITrack2, 0, 1, 60, 50, 480); /* ど */
	MIDITrack_InsertNote(pMIDITrack2, 0, 1, 64, 50, 480); /* み */
	MIDITrack_InsertNote(pMIDITrack2, 0, 1, 67, 50, 480); /* そ */
	MIDITrack_InsertNote(pMIDITrack2, 0, 1, 60, 50, 480); /* ど */

	/* エンドオブトラックイベントを挿入 */
	MIDITrack_InsertEndofTrack(pMIDITrack2, 500);

	/* MIDIデータを保存 */
	MIDIData_SaveAsSMF(pMIDIData, L"メロディ&伴奏.mid");

	/* MIDIデータをメモリ上から削除 */
	MIDIData_Delete(pMIDIData);
	pMIDIData = NULL;
	return 1;
}
ちなみに
トラックを取得する際、MIDIData_GetTrack (MIDIData* pMIDIData, long lTrackIndex)という関数があったんですが、
内部では、単純にforでMIDITrack_GetNextTrackを繰り返すような感じだったので、そのままMIDITrack_GetNextTrackを使うことにしました。
オフトピック
「失敗した」「うまくいかない」では、なにがやりたいのか、失敗した結果どうなっているのかの情報が1byteも入ってこないです。
(「うまく再生されない」ってつまり、エラーを吐く?音がおかしい?極端に短い?途中で止まる?)
問題があれば、具体的に何が起こったのか、教えてくれると嬉しいです。

kero_nao

Re: ■□MIDIDataライブラリについて質問です□■

#7

投稿記事 by kero_nao » 7年前

>Teppさん

ありがとうございます!無事に動きました!
どうやら、私のMIDITrackとMIDIDataポインタの認識ついて、
間違いがあったようです。
もう一度リファレンスを見直そうと思います。

皆様、たくさんのアドバイスありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る