}
}
}
+ public double 長さsec
+ {
+ get
+ {
+ lock( this.排他利用 )
+ {
+ return ( this.サウンドデータサイズsample / this.WAVEフォーマット.SampleRate );
+ }
+ }
+ }
public Sound()
{
{
mediaType.Set<Guid>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.MajorType, SharpDX.MediaFoundation.MediaTypeGuids.Audio );
mediaType.Set<Guid>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.Subtype, SharpDX.MediaFoundation.AudioFormatGuids.Pcm );
- mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioNumChannels, 2 );
- mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioSamplesPerSecond, 44100 );
- mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioBlockAlignment, 4 );
- mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioAvgBytesPerSecond, 4 * 44100 );
- mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioBitsPerSample, 16 );
+ mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioNumChannels, this.WAVEフォーマット.Channels );
+ mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioSamplesPerSecond, this.WAVEフォーマット.SampleRate );
+ mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioBlockAlignment, this.WAVEフォーマット.BlockAlign );
+ mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioAvgBytesPerSecond, this.WAVEフォーマット.AverageBytesPerSecond );
+ mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AudioBitsPerSample, this.WAVEフォーマット.BitsPerSample );
mediaType.Set<int>( SharpDX.MediaFoundation.MediaTypeAttributeKeys.AllSamplesIndependent, 1 ); // TRUE
// 作成したメディアタイプを sourceReader にセットする。sourceReader は、必要なデコーダをロードするだろう。
this.作成済み = true;
}
}
- public void 再生を開始する()
+ public void 再生を開始する( double 再生開始位置sec = 0.0 )
{
lock( this.排他利用 )
{
if( false == this.作成済み )
return; // エラーにはしない。サウンド作成失敗時には、何も再生しないようにするだけ。
- this.再生状態 = E再生状態.再生中;
- this.再生位置sample = 0; // 再生位置を先頭へ。
+ int 開始位置sample = (int) ( 再生開始位置sec * this.WAVEフォーマット.SampleRate );
+ if( 開始位置sample < this.サウンドデータサイズsample )
+ {
+ this.再生状態 = E再生状態.再生中;
+ this.再生位置sample = 開始位置sample;
+ }
}
}
public void 再生を一時停止する()
private int サウンドデータサイズbyte = 0;
private int サウンドデータサイズsample = 0;
private int 再生位置sample = 0;
+ private readonly SharpDX.Multimedia.WaveFormat WAVEフォーマット = new SharpDX.Multimedia.WaveFormat( 44100, 16, 2 ); // 固定
private readonly object 排他利用 = new object();
#region " バックストア "
public Action コンボリセット = null;
public Action コンボ加算 = null;
public Action<ヒット判定種別> ヒット判定数加算 = null;
- public Action 背景動画再生開始 = null;
+ public Func<double> 背景動画の長さsec = null;
+ public Action<double> 背景動画再生開始 = null;
public Action<SSTFormat.チップ> チップヒット = null;
public Action ステージクリア = null;
public Func<double> リアルタイム演奏時刻sec = null;
if( null == スコア )
return 0.0;
+ double 演奏開始時刻sec = 0.0;
for( int i = 0; i < スコア.チップリスト.Count; i++ )
{
var チップ = スコア.チップリスト[ i ];
else
{
this.描画開始チップ番号 = i;
- return チップ.発声時刻sec - 0.5; // ちょっと早めの時刻を返す。
+ 演奏開始時刻sec = チップ.発声時刻sec - 0.5; // ちょっと早めの時刻にする。
+ break;
+ }
+ }
+
+ // 背景動画チップがあり、かつ再生中の位置であるなら、適切な位置から再生を開始する。
+ foreach( var チップ in スコア.チップリスト )
+ {
+ if( チップ.チップ種別 == SSTFormat.チップ種別.背景動画 )
+ {
+ if( ( チップ.発声時刻sec <= 演奏開始時刻sec ) &&
+ ( 演奏開始時刻sec < ( チップ.発声時刻sec + this.背景動画の長さsec() ) ) )
+ {
+ this.背景動画再生開始( 演奏開始時刻sec - チップ.発声時刻sec );
+ }
+ break;
}
}
- return 0.0;
+
+ return 演奏開始時刻sec;
}
public void 演奏を停止する()
if( chip.チップ種別 == SSTFormat.チップ種別.背景動画 )
{
// (A) 背景動画の場合。
- this.背景動画再生開始?.Invoke();
+ this.背景動画再生開始?.Invoke( 0.0 );
}
else
{
this.スクロール譜面.ヒット判定数加算 = ( hitType ) => {
this.ヒットした回数[ hitType ]++;
};
- this.スクロール譜面.背景動画再生開始 = () => {
+ this.スクロール譜面.背景動画の長さsec = () => {
+ return ( null != this.BGM ) ? this.BGM.長さsec : 0.0;
+ };
+ this.スクロール譜面.背景動画再生開始 = ( 開始位置sec ) => {
+ //this.背景動画.再生位置を移動する( 開始位置sec );
this.背景動画開始済み.Value = true;
- this.BGM?.再生を開始する();
+ this.BGM?.再生を開始する( 開始位置sec );
this.BGM再生開始済み = true;
};
this.スクロール譜面.チップヒット = ( chip ) => {