         LoadWavFromPath(path: "vaiueo2d")
         loadEffectData(particlePath: maleStandPath!,shadowParticlePath: maleShadowPath!)
     }
-
-    
-    //すべてに共通するアプリスタート時の一番最初の設定
+    
+    //--------------------------
+    //------ReplayFunction------
+    //--------------------------
+    //直前の一連操作において操作位置とF0を保存しておいたものを、現状のタイマー環境を用いて無理やり再現してるだけ
+    @IBAction func Tap_Replay(_ sender: Any) {
+        if replayIndexArray.count != 0{ //何かしら操作があったら
+            replayMode = true           //Replay使えるよ！このMode変更によってSetBufferTimerの動きが変更
+            
+            //バッファ再生の構成上、予め最初のバッファは読み込んで再生する。
+            syntheIndex = Int32(replayIndexArray[replayIndex]) + Int32(f0_start)
+            SynthesisToBuffer(syntheIndex: syntheIndex, buffer_num: buffer_num)
+            syntheNode.scheduleBuffer(buffers[buffer_num],at:nil,completionHandler:nil)
+            replayIndex += 1
+            
+            FuncAllTap(flag: false)
+            
+            //Replay中だよ！って画面にフェードイン・フェードアウトしながら表示する豪華なエフェクト
+            ShowLabelWithAnimation(label: replayLabel)
+        }
+    }
+    
+    //--------------------------
+    //-------TimerProcess-------
+    //--------------------------
+
+    //すごい早く繰り返されるタイマーで、合成可能になったら大急ぎで合成してPCMBufferに一時保存する
+    func SynthesisTimer(tm: Timer) {
+        if canSynthe{
+            SynthesisToBuffer(syntheIndex: syntheIndex, buffer_num: synthe_bufferNum)
+            canSynthe = false
+        }
+    }
+
+    //BufferSizeに対応した速度で繰り返されるタイマーで、ちょうどいい素晴らしいタイミングで次のバッファを再生用のNodeに詰め込む
+    //ここでは、リプレイモードか、操作モードかで大きく機構が分岐する
+    func SetBufferTimer(tm: Timer) {
+        //リプレイモード時の動作
+        if CanReplay(replayMode: replayMode, replayIndexArray: replayIndexArray) {
+            //次の合成していいよ
+            canSynthe = true
+            //次のバッファを再生用Nodeに末尾追加
+            syntheNode.scheduleBuffer(buffers[next_bufferNum],at:nil,completionHandler:nil)
+            //次の合成位置を格納しておく
+            syntheIndex = Int32(replayIndexArray[replayIndex]) + Int32(f0_start)
+            //その位置のF0worldParameterを操作時のf0に変えておく
+            world_parameter?.f0[Int(syntheIndex)] = Double(replayF0Array[Int(replayIndex)]!)
+            //再現位置にParticleを移動
+            MoveParticle(x: replayIndexArray[replayIndex] * xAxisMargin,y: replayF0Array[replayIndex]!, moveSpeed: particleMoveSpeed)
+            //次のリプレイ位置へ加算
+            replayIndex += 1
+            
+            //リプレイ終了時の処理
+            if replayIndexArray.count == replayIndex{
+                replayIndex = 0
+                replayMode = false
+                FuncAllTap(flag:true)
+                replayLabel.removeFromParent()
+            }
+        }else{
+        //操作モード時の動作
+            if tapIndex != 0.0{ //どこかタップしていたら
+                //次の合成していいよ
+                canSynthe = true
+                //次のバッファを再生用Nodeに末尾追加
+                syntheNode.scheduleBuffer(buffers[next_bufferNum],at:nil,completionHandler:nil)
+                //合成位置を格納
+                syntheIndex = Int32(tapIndex + CGFloat(f0_start))
+                
+                //Replay時のためにIndexとF0を保存
+                replayIndexArray.append(tapIndex)
+                replayF0Array.append(f0Array[Int(tapIndex)])
+                
+            }
+        }
+        //次のバッファの設定
+        buffer_num=(buffer_num+1)%buffer_cnt
+        next_bufferNum = (buffer_num+1)%buffer_cnt
+        synthe_bufferNum = (next_bufferNum+1)%buffer_cnt
+        
+        if replayIndexArray.count == 0{
+            replayButton.isHighlighted =  true
+        }
+    }
+
+    
+    //--------------------------
+    //-------Initializer--------
+    //--------------------------
+    
+    //画面上の初期化
     func InitializeView(){
-        //操作画面の設定
         standEffect = SKView(frame:CGRect(x: 0, y: HeaderFooter, width: Int(self.view.frame.width), height: AllViewY-HeaderFooter*2))
-        //本UI画面の設定
         self.standScene = SKScene(size:CGSize(width:self.view.frame.width,height:CGFloat(AllViewY-HeaderFooter*2)))
         standEffect!.presentScene(standScene)
-        //グラフの高さの設定
-        graphViewHeight = AllViewY - HeaderFooter*2
-    }
-    //すべてに共通する画像系のデータ読み込み
-    func loadingViewData(){
-        //Stand背景の設定
         let backGround = SKSpriteNode(imageNamed:"background")
         self.standScene?.addChild(backGround)
-        //self.view.sendSubview(toBack: background)
-    }
+    }
+    
+    //エフェクトデータの読み込み
     func loadEffectData(particlePath:String,shadowParticlePath:String){
         particle.removeFromParent()
         shadow.removeFromParent()

        
        let changeWidth = 1
        //触れている場所を検出し、f0配列の値を変える。WORLDParameterも変更する。
        ChangeF0Line(y: y, changeWidth: changeWidth)
        
        preIndex = index
        preY = y
    }
    func ChangeF0Line(y:CGFloat,changeWidth:Int){
        if(preIndex != 0.0)
        {
            var y1:CGFloat = 0

        femaleCnt = femaleCnt+1
        return path
    }
    
    //Recording!とかReplay!とかのラベルを豪華なアニメーションで再生してくれるメソッド
    func ShowLabelWithAnimation(label:SKLabelNode){
        label.fontName = "Snell Roundhand"
        label.position = CGPoint(x:standScene!.size.width / 4 * 2,y:(standScene?.size.height)! / 2)
