原則としてオリジナルのソースに手を加えた部分のみ記述
オリジナルのソースコードに Kobarin が手を加えた箇所には "Kobarin" という
文字列が含まれる

v0.22/v0.23
・playmidi.c
    ・#define REDUCE_VOICE_TIME_TUNING を削除(演奏がおかしくなる)
・playmidi.c::free_reverb_buffer()
  ・//修正 by Kobarin
    //reverb_buffer を NULL にセットしておかないと、
    //free_reverb_buffer 呼出し後に do_compute_data_midi を呼ぶと落ちる
    reverb_buffer = NULL;//added by Kobarin
・readmidi.c::read_midi_file
  ・不要なコードを取り払ったものに置き換え
・readmidi.c::get_midi_title
  ・不要なコードを取り払ったものに置き換え
・readmidi.c::read_sysex_event を修正
  ・memset(evm, 0, sizeof(evm));//added by Kobarin
  ・readmidi.c::parse_sysex_event_multi の内部で evm を初期化していない
    ところがあるので、parse_sysex_event_multi を呼び出す前に配列 evm を
    初期化するように修正
  ・evm.type を ME_EOT で初期化しておいた場合に、最後まで演奏されない
    データはこのバグの修正の影響を受ける
  ・配列 evm を初期化しておかないと、実際は終了していないのに演奏終了
    してしまったり、再生する度に再生結果が変化することがある。
    もしかしたら不正終了することもあるかも。
・readmidi.c::groom_list()
  ・counting_time を 0 に修正
  ・冒頭の無音を無視しないようにするため(歌詞表示がずれるのを防ぐ)
・readmidi.c::free_userdrum()
    //init_userdrum() 呼び出し時に drumset[64+0]->alt, drumset[64+1]->alt でそ
    //れぞれ 20 バイト(=sizeof(AlternateAssign))のメモリリーク
    //readmidi.c::free_userdrum() を以下のように修正
    //added by Kobarin
    int i;
    for(i = 0; i < 2; i++){
        if(drumset[64+i] && drumset[64+i]->alt){
            struct _AlternateAssign *alt = drumset[64+i]->alt;
            struct _AlternateAssign *del=alt;
            while(del){
                alt=del->next;
                free(del);
                del=alt;
            }
            drumset[64+i]->alt = NULL;
        }
    }
    //ここまで
    //これを追加しなくても、ファイルを開く度に init_userdrum で
    //前回の呼び出し時に確保したメモリは解放されているが、アプリケーション
    //終了時には解放されないので、追加しておいた方が良いと思われる。
・recache.c::free_cache_data()
  ・cache_data を NULL にセットしていないので、次の resamp_cache_reset 呼び出し
    時にメモリアクセス違反発生
    //修正 by Kobarin
    //free(cache_data);
    //reuse_mblock(&hash_entry_pool);
    //cache_data を NULL にしておかないと、この関数呼び出し後に
    //resamp_cache_reset を呼ぶと落ちる
    if(cache_data){
        free(cache_data);
        cache_data = NULL;
        reuse_mblock(&hash_entry_pool);
    }
    //ここまで
・sndfont.c::free_soundfonts()
  ・最終行に sfrecs = NULL; を追加
・freq.c::freq_initialize_fft_arrays()
  ・メモリリーク修正その1
    //if (oldfftsize > 0){//del by Kobarin
    if(magdata){//add by Kobarin(前回が length == 0 だったときにメモリリーク)
  ・メモリリーク修正その2
    ・終了時に magdata 等が解放されないので 
      free_freq_data_by_Kobarin を新設して対処(本家に解放用の関数が新設されれば
      不要になる)
  ・メモリ破壊修正
    //ip = (int *) safe_malloc(2 + sqrt(length) * sizeof(int));//del by Kobarin
    //修正 by Kobarin
    //length == 0 のときにメモリを破壊する
    //2+sqrt(length) の 2 == 16bit 時代の sizeof(int)?
    //(1+sqrt(length))*sizeof(int) で良いかも
    ip = (int*)safe_malloc((2+sqrt(length))*sizeof(int));
    //ここまで
・instrum.c::free_tone_bank_list()
  ・メモリリーク修正(2箇所修正)
  ・1つ目
    //for (i = 0; i < 128 + map_bank_counter; i++)//del by Kobarin
    for(i = 0; i < 128 + MAP_BANK_COUNT; i++)//add by Kobarin(メモリリーク修正)
  ・2つ目
    {//added by Kobarin(メモリリーク修正)
        struct _AlternateAssign *del=bank->alt;
        struct _AlternateAssign *next;
        while(del){
            next=del->next;
            free(del);
            del=next;
        }
        bank->alt = NULL;
    }//ここまで
  ・v0.21 以前で行っていた free_tone_bank() の修正が不要となった(↑の1つ目の修
    正が相当する)
  ・v0.21 以前の free_userdrum2() が不要となった(↑の2つ目の修正が相当する)
・resample.c::resample_linear
  ・2.14.0(2012/06/29) 以降、謎の不具合(ofs が異常な値を示してメモリアクセス違
    反が発生)が確認出来なくなったので _resample_.c を廃止し、普通に resample.c
    をプロジェクトに追加

v0.20
  ・sndfont.c::free_soundfonts()
    最後の行に sfrecs = NULL; を追加(v0.07 のときとは修正の仕方が異なる)
  ・freq.c::freq_initialize_fft_arrays()
    メモリリーク修正
    //if (oldfftsize > 0)//del by Kobarin
    if(magdata)//add by Kobarin
  ・主にメモリリーク対策用に新設した関数名の後ろに _by_Kobarin を付加
v0.19
  ・reverb.c::init_ch_3tap_delay, init_ch_reverb_delay を修正
    http://sabao.hp.infoseek.co.jp/ にある toughguy.mid を再生すると落ちる
  ・CVS081206 で対策されたので v0.20 で修正不要となった
v0.17
  ・freq.c::freq_initialize_fft_arrays を修正
    length == 0 のときに落ちる
  ・v0.20 でも要修正

v0.09
・readmidi.c::read_sysex_event を修正 (v0.20 でも修正必要)
  ・readmidi.c::parse_sysex_event_multi の内部で evm を初期化していない
    ところがあるので、parse_sysex_event_multi を呼び出す前に配列 evm を
    初期化するように修正
    SETMIDIEVENT(evm[num_events], x, x, x, x, x);
    のように呼び出している部分のいくつかが、なぜか evm[0] とかになって
    いるのが気になる…。evm[0] とかにしている部分では num_events を
    インクリメントしてはまずいような…。
  ・evm.type を ME_EOT で初期化しておいた場合に、最後まで演奏されない
    データはこのバグの修正の影響を受ける
  ・配列 evm を初期化しておかないと、実際は終了していないのに演奏終了
    してしまったり、再生する度に再生結果が変化することがある。
    もしかしたら不正終了することもあるかも。

v0.08
・シーク対応のために play_midi.c に g_midi_start_time を追加していた
  のを廃止。play_midi.c を書き換えずにシークに対応

v0.07
・sffile.c::free_layer() 修正（メモリリーク回避）
  ・v0.20 から修正不要となった
・sndfont.c::free_soundfonts() 追加（メモリリーク回避） 
  ・v0.20 から修正の仕方が変わった
・instrum.c::free_tone_bank 修正（メモリリーク回避）
  ・v0.20 でも要修正

v0.06
・read_midi.c を修正
  ・groom_list() の counting_time を 0 に修正
  ・冒頭の無音を無視しないようにするため
  ・v0.20 でも要修正

v0.05
・play_midi.c を修正
  ・シークに対応するため、グローバル変数 g_midi_start_time を追加
  ・play_midi() 関数の skip_to() の引数を midi_restart_time から
    g_midi_start_time に変更
  ・ctl_read で RC_JUMP を返すようにすることで対応できるはずなのだが、
    演奏開始直後に再生位置を変更しようとするとうまくいかない

v0.04
・resample.c を修正（実際は resample.c を書き換えずに _resample_.c を
  修正しただけ）
  ・resample_linear 等の ofs 値に負の値が渡されて落ちることがある問題に
    暫定対処
    ・確認データ：DQS8P.MID by TRIGLAV
    ・演奏開始後7分2秒くらいの位置で発生
    ・シークしないで演奏すると確実に発生、シークしたときは発生するとき
      としないときがある
    ・コンフィグファイルの内容によっては発生しない
  ・そもそも ofs 値に負の値が渡されることがおかしい
  ・負の値でなくても、不正に大きな値が渡されることもあるかもしれない
  ・resample_linear 以外を使う分にはなぜか問題が起こらない
  ・どこか全然関係ない部分に問題があるのかも？
・common.c::try_to_open()
  ・オリジナルをそのまま使うように修正。最新版取り込み時に修正する必要が
    なくなった

v0.03 以前

メモ：

オリジナルのソースコードは TiMidity++-current-040525-0000
出来るだけオリジナルのソースコードには修正を加えないようにしている。
修正しているファイルは以下の通り。

・config.h    (末尾に #include "kbtim\kbtim_config.h")
・interface.h (末尾に #include "kbtim\kbtim_interface.h")
・playmidi.c  (#define REDUCE_VOICE_TIME_TUNING を削除、
               グローバル変数 g_midi_start_time を追加、
               play_midi_file() を修正)
・readmidi.c  (read_midi_file(), open_midi_file(), get_midi_title())
・resample.c （resample_inline() を追加他）
//・common.c    (try_to_open())

上記５ファイルについては、最新の TiMidity のソースコードを組み込むときにも修正
する必要がある。

バグ：

・aq.c
・recache.c
・resample.c
・playmidi.c
・readmidi.c

上記５ファイルでメモリリークを確認している。
おそらくメモリ解放用の関数を追加しないと回避不可能と思われる。
このうち、上記４ファイルについては、それぞれ

・_aq_c
・_recache_.c
・_resample_.c
・_playmidi_.c

でオリジナルを #include し、メモリ解放関数を追加することにより、メモリリークを
回避している。（オリジナルのソースコード自体は一切修正していない）
オリジナルにメモリ解放関数が実装されれば、これらの修正は不要になる。

readmidi.c については free_userdrum と free_all_midi_file_info を修正、
free_userdrum2 を新設することにより、メモリリークを回避。（詳細は後述）


具体的な修正箇所：

・config.h
    //ヘッダの末尾に以下を追加
    //#ifdef KBTIM /*added by Kobarin*/
    //#include "kbtim\kbtim_config.h"
    //#endif /*KBTIM*/

・interface.h
    //ヘッダの末尾に以下を追加
    //#ifdef KBTIM /*added by Kobarin*/
    //#include "kbtim\kbtim_interface.h"
    //#endif /*KBTIM*/

・playmidi.c
    //メモリリーク
    //アプリケーション終了時に free_reverb を呼び出すようにする、あるいは
    //free_reverb のバッファを動的に確保するのではなく、静的に確保しておく
    //ようにすることにより回避。
    //詳細は _playmidi_.c を参照。

・playmidi.c::REDUCE_VOICE_TIME_TUNING
    //#define されていると再生結果がおかしくなる（kbtim.kpi 固有の問題）
    //（CPU に負担がかかりすぎであると誤認識してしまうため）
    //宣言部の
    //#define REDUCE_VOICE_TIME_TUNING
    //を削除することにより回避。
    //この部分は config.h に移動した方が良いと思われる。

・readmidi.c::init_userdrum()
    //drumset[64+0]->alt, drumset[64+1]->alt でそれぞれ 20 バイトのメモリリーク
    //readmidi.c::free_userdrum() を以下のように修正
    //added by Kobarin
    //int i;
    //for(i = 0; i < 2; i++){
    //    if(drumset[64+i] && drumset[64+i]->alt){
    //        free(drumset[64+i]->alt);
    //        drumset[64+i]->alt = NULL;
    //    }
    //}
    //ここまで
    //これを追加しなくても、ファイルを開く度に init_userdrum で
    //前回の呼び出し時に確保したメモリは解放されているが、アプリケーション
    //終了時には解放されないので、追加しておいた方が良いと思われる。

・readmidi.c
    //コンフィグファイル読み込み時（？）に確保した drumset 関係のメモリリーク
    //readmidi.c に以下の関数を追加
    //void free_userdrum2()
    //{
    //int i;
    //for(i = 0; i < 128 + MAP_BANK_COUNT; i++){
    //    if(drumset[i] && drumset[i]->alt){
    //        struct _AlternateAssign *alt = drumset[i]->alt;
    //        struct _AlternateAssign *del=alt;
    //        while(del){
    //            alt=del->next;
    //            free(del);
    //            del=alt;
    //        }
    //        drumset[i]->alt = NULL;
    //    }
    //}
    //アプリケーション終了時 or コンフィグファイルリロード時にこれを呼び出す。
    //ファイルを再生する度に呼び出すと、コンフィグファイル読み込み時に drumset
    //を設定した意味がなくなってしまう。
}

・readmidi.c::free_all_midi_file_info()
    //メモリリーク
    if(string_event_table != NULL)//added by Kobarin
    {
    free(string_event_table[0]);
    free(string_event_table);
    string_event_table = NULL;
    string_event_table_size = 0;
    }
    //これを追加しなくても、ファイルを開く度に readmidi_read_init で
    //解放されているが、アプリケーション終了時には解放されないので
    //追加しておいた方が良いと思われる。
  ・CVS081206 以降、free_readmidi() を呼べば解決
・readmidi.c::read_midi_file()
    //大幅に修正（不要なコードを削除）

・readmidi.c::open_midi_file()
    //大幅に修正（不要なコードを削除）

・readmidi.c::get_midi_title()
    //大幅に修正（不要なコードを削除）
    
・common.c
    //try_to_open を大幅修正（ファイルサイズが小さくなる）
    //修正しないとリンカエラー。

・aq.c::alloc_soft_queue()
    //メモリリーク
    //この関数で確保した base_buckets がアプリケーション終了時に
    //解放されない。
    //アプリケーション終了時 or 演奏終了時に free_audio_bucket()
    //を呼び出すようにすることにより回避。
    //詳細は _aq_.c を参照。
    //free_audio_bucket がオリジナルに組み込まれれば、_aq_.c は不要に
    //なり、aq.c をそのままプロジェクトに追加するだけで良くなる。

・recache.c::resamp_cache_reset
    //メモリリーク
    //アプリケーション終了時に free_resamp_cache_data を呼び出す
    //ことにより回避。
    //詳細は _recache_.c を参照。
    //resamp_cache_reset がオリジナルに組み込まれれば、_recache_.c は不要に
    //なり、recache.c をそのままプロジェクトに追加するだけで良くなる。

・resample.c::initialize_gauss_table
    //メモリリーク
    //アプリケーション終了時に uninitialize_resampler_coeffs を呼び出す
    //ことにより回避。
    //詳細は _resample_.c を参照。
    //uninitialize_resampler_coeffs がオリジナルに組み込まれれば、
    //_resample_.c は不要になり、resample.c をそのままプロジェクトに
    //追加するだけで良くなる。

・output.c
    //プロジェクトには追加していない。
    //代わりに _output_.c を追加。
    //不要なコードを削除。（ファイルサイズが小さくなる）
    //そのまま output.c を使うとリンカエラー。

・w32g_utl.c
    //プロジェクトには追加していない。
    //代わりに _w32g_utl.c を追加。
    //不要なコードを削除。（ファイルサイズが小さくなる）
    //そのまま w32g_utl.c を使うとリンカエラー。

最新の TiMidity を組み込む場合に確認するべき箇所：

・config.h
    //ヘッダの末尾に以下を追加
    //#ifdef KBTIM /*added by Kobarin*/
    //#include "kbtim\kbtim_config.h"
    //#endif /*KBTIM*/
・interface.h
    //ヘッダの末尾に以下を追加
    //#ifdef KBTIM /*added by Kobarin*/
    //#include "kbtim\kbtim_interface.h"
    //#endif /*KBTIM*/
・output.c
    //general_output_convert で新しくサポートされたフォーマットが
    //ないか確認。（32bit int/float など）
・w32g_utl.c
    //設定読み込み部分で、追加された設定がないか確認・
    //追加された設定があり、それが kbtim.kpi の動作（音質面など）
    //に影響がある場合は、_w32g_utl_.c に反映させる。
・timidity.c/_timidity_.c
    //timidity_start_initialize での修正を kbtim_start_initialize に反映させる。
    //timidity_pre_load_configuration での修正を kbtim_pre_load_configuration に反映させる。
    //timidity_post_load_configuration での修正を kbtim_post_load_configuration に反映させる。
    //timidity_init_player での修正を kbtim_init_player に反映させる。
・playmidi.c
    //#define REDUCE_VOICE_TIME_TUNING を削除する。
・readmidi.c::read_midi_file()
・readmidi.c::open_midi_file()
・readmidi.c::get_midi_title()
・readmidi.c::free_userdrum()
・readmidi.c::free_userdrum2()
・readmidi.c::free_all_midi_file_info()
・common.c::try_to_open()
・最新のソースに置き換えるとリンカエラーが発生する場合
    //原因となるグローバル変数・関数が kbtim.kpi の動作に影響がない場合
    //は、kbtim_globals.c で実装する。
    //例えば最新のソースで新たに追加された int foo(int a); という関数と
    //リンク出来ないのが原因でリンカエラーになる場合は、foo を実装して
    //いるソースファイルをプロジェクトに追加するか、あるいは
    //int foo(int a){return 0;}
    //を kbtim_globals.c に追加するなど。
    //ただし、このような修正が kbtim.kpi の動作にどのような影響を与えるのか
    //十分に考慮しておく必要がある。
