AndroidからPCへタップ座標値をUDPで送信（複数のタップアイコンを制御する）

■プログラムの概要
　・前回投稿（＊）の改良版です。複数のタップアイコンを選択的に制御できるように
　　しました。但し、同時制御（マルチタップ）ではありませんので、ご注意ください。
　　（＊）https://qiita.com/voibow/items/e64ca603d84cb4ba5534
　・用途：電子楽器。※YouTube動画リンク先：**https://youtu.be/_rWSoXfOAH0**

■Android側のプログラムのソースコード
　（補足）各種アイコン（glitter_icon.png等）や背景画像（bg.jpg）は、pptで作成。
```java:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fed"
    tools:context="com.example.Flt_Atk_Oct_20220601.MainActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="image1"
        android:scaleType="centerCrop"
        android:src="@drawable/bg" />

    <TextView
        android:id="@+id/text_view_apt"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="185dp"
        android:layout_marginLeft="110dp"
        android:textSize="50sp"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_cav"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="0dp"
        android:layout_marginLeft="25dp"
        android:textSize="50sp"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_flt"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="0dp"
        android:layout_marginLeft="320dp"
        android:textSize="25sp"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_atk"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="90dp"
        android:layout_marginLeft="320dp"
        android:textSize="25sp"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_oct"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="180dp"
        android:layout_marginLeft="320dp"
        android:textSize="25sp"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_x0"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="243dp"
        android:layout_marginLeft="125dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_y0"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="243dp"
        android:layout_marginLeft="225dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_x1"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="62dp"
        android:layout_marginLeft="420dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_y1"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="62dp"
        android:layout_marginLeft="520dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_x2"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="155dp"
        android:layout_marginLeft="420dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_view_y2"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="155dp"
        android:layout_marginLeft="520dp"
        android:textSize="20sp"
        android:textColor="#ffffff"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.Flt_Atk_Oct_20220601.CustomImageView
        android:id="@+id/image_view_glitter"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="0dp"
        android:layout_marginTop="140dp"
        android:src="@drawable/glitter_icon"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.Flt_Atk_Oct_20220601.CustomImageView
        android:id="@+id/image_view_flutter"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="350dp"
        android:layout_marginTop="0dp"
        android:src="@drawable/flutter_icon"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.Flt_Atk_Oct_20220601.CustomImageView
        android:id="@+id/image_view_attack"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="350dp"
        android:layout_marginTop="95dp"
        android:src="@drawable/attack_icon"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.Flt_Atk_Oct_20220601.CustomImageView
        android:id="@+id/image_view_octave0"
        android:layout_width="320dp"
        android:layout_height="325dp"
        android:layout_marginLeft="350dp"
        android:layout_marginTop="119dp"
        android:src="@drawable/oct_down_icon"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
   </RelativeLayout>
```

```java:MainActivity.java
//参照サイト：https://www.wabiapp.com/WabiSampleSource/windows/udp_server.html

package com.example.Flt_Atk_Oct_20220601;

import androidx.appcompat.app.AppCompatActivity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class MainActivity extends AppCompatActivity
        implements View.OnTouchListener {

    // 各種変数宣言
    CustomImageView[] cImageView = new CustomImageView[5];
    TextView textView_apt, textView_cav, textView_flt;
    TextView textView_x0,textView_y0,textView_x1,textView_y1;//デバッグ用途
    TextView textView_x2,textView_y2;//デバッグ用途
    // タップ座標、エリア
    int[] newDx = new int[5];    int[] newDy = new int[5];
    int[] preDx = new int[5];    int[] preDy = new int[5];
    int[] max_x = new int[5];    int[] max_y = new int[5];
    int[] min_x = new int[5];    int[] min_y = new int[5];
    int tap_area;  boolean oct_button;
    // パソコンに送信する値
    int posi_apt, posi_cav, posi_flt, posi_atk, posi_oct;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 横画面に固定する
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // 画像表示
        textView_apt = findViewById(R.id.text_view_apt);
        textView_cav = findViewById(R.id.text_view_cav);
        textView_flt = findViewById(R.id.text_view_flt);
        textView_atk = findViewById(R.id.text_view_atk);
        textView_oct = findViewById(R.id.text_view_oct);
        cImageView[0] = this.findViewById(R.id.image_view_glitter);
        cImageView[1] = this.findViewById(R.id.image_view_flutter);
        cImageView[2] = this.findViewById(R.id.image_view_attack);
        cImageView[3] = this.findViewById(R.id.image_view_octave0);
        cImageView[0].setOnTouchListener(this);
        cImageView[1].setOnTouchListener(this);
        cImageView[2].setOnTouchListener(this);
        cImageView[3].setOnTouchListener(this);
        // デバッグ表示用の変数定義
        textView_x0 = findViewById(R.id.text_view_x0);
        textView_y0 = findViewById(R.id.text_view_y0);
        textView_x1 = findViewById(R.id.text_view_x1);
        textView_y1 = findViewById(R.id.text_view_y1);
        textView_x2 = findViewById(R.id.text_view_x2);
        textView_y2 = findViewById(R.id.text_view_y2);
        // 初期設定（画面の各エリア範囲を規定）
        max_x[0]=720; min_x[0]=200; max_y[0]=650; min_y[0]=200;//glitterエリア
        max_x[1]=1600; min_x[1]=1300; max_y[1]=200; min_y[1]=100;//flutterエリア
        max_x[2]=1600; min_x[2]=1300; max_y[2]=550; min_y[2]=350;//attackエリア
        max_x[3]=1600; min_x[3]=1300; max_y[3]=750; min_y[3]=650;//octaveエリア
        tap_area = -1;//どのエリアでもない
        oct_button = false;// 通常ピッチ（octシフトしていない）
        // 初期表示
        String str_apt = "apt=" + 100;
        textView_apt.setText(str_apt);
        String str_cav = "cav=" + 100;
        textView_cav.setText(str_cav);
        String str_flt = "flt=" + 0;
        textView_flt.setText(str_flt);
        String str_atk = "atk=" + 0;
        textView_atk.setText(str_atk);
        String str_oct = "oct=" + 0;
        textView_oct.setText(str_oct);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //タップ座標＠アイコンの取得、各アイコンのエリア規定
        newDx[0] = Math.min(Math.max((int)event.getRawX(),min_x[0]),max_x[0]);
        newDy[0] = Math.min(Math.max((int)event.getRawY(),min_y[0]),max_y[0]);
        newDx[1] = Math.min(Math.max((int)event.getRawX(),min_x[1]),max_x[1]);
        newDy[1] = Math.min(Math.max((int)event.getRawY(),min_y[1]),max_y[1]);
        newDx[2] = Math.min(Math.max((int)event.getRawX(),min_x[2]),max_x[2]);
        newDy[2] = Math.min(Math.max((int)event.getRawY(),min_y[2]),max_y[2]);
        newDx[3] = Math.min(Math.max((int)event.getRawX(),min_x[3]),max_x[3]);
        newDy[3] = Math.min(Math.max((int)event.getRawY(),min_y[3]),max_y[3]);

        if(newDx[0]<max_x[0] && newDx[0]>=min_x[0] && newDy[0]<max_y[0] && newDy[0]>=min_y[0]) {
            tap_area = 0;//glitterエリア
            // 【デバッグ表示】newDxなど
            String str_x0 = "x0=" + newDx[0];
            textView_x0.setText(str_x0);
            String str_y0 = "y0=" + newDy[0];
            textView_y0.setText(str_y0);
        }
        else if(newDx[1]<max_x[1] && newDx[1]>=min_x[1] && newDy[1]<max_y[1] && newDy[1]>=min_y[1]) {
            tap_area = 1;//flutterエリア
            // 【デバッグ表示】newDxなど
            String str_x1 = "x1="  + newDx[1];
            textView_x1.setText(str_x1);
            String str_y1 = "y1=" + newDy[1];
            textView_y1.setText(str_y1);
        }
        else if(newDx[2]<max_x[2] && newDx[2]>=min_x[2] && newDy[2]<max_y[2] && newDy[2]>=min_y[2]) {
            tap_area = 2;//attackエリア
            // 【デバッグ表示】newDxなど
            String str_x2 = "x2="  + newDx[2];
            textView_x2.setText(str_x2);
            String str_y2 = "y2=" + newDy[2];
            textView_y2.setText(str_y2);
        }
        else if(newDx[3]<max_x[3] && newDx[3]>=min_x[3] && newDy[3]<max_y[3] && newDy[3]>=min_y[3]) {
            tap_area = 3;//octaveエリア
        }
        else {
            tap_area = -1;//どのエリアでもない
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:// オクターブ切替のみタッチ制御にする
                if(tap_area == 3) {
                    if(oct_button) {
                        cImageView[3].setImageResource(R.drawable.oct_down_icon);
                        cImageView[3].setAlpha(0.0f);//0：透明 ～ 1：非透明
                        oct_button = !oct_button;
                        posi_oct = 0;
                    }
                    else {
                        cImageView[3].setImageResource(R.drawable.oct_down_icon);
                        cImageView[3].setAlpha(1.0f);//0：透明 ～ 1：非透明
                        oct_button = !oct_button;
                        posi_oct = 1;
                    }
                   // パラメータ値の画面表示
                    String str_oct = "oct=" + posi_oct;
                    textView_oct.setText(str_oct);
                }
                break;
            case MotionEvent.ACTION_UP://何もしない
                break;
            case MotionEvent.ACTION_MOVE:
                int dx,dy,imgW,imgH;
                // glitterエリアでの処理
                if(tap_area == 0) {
                    // 画像タップ位置を決定
                    dx = cImageView[0].getLeft() + (newDx[0] - preDx[0]);
                    dy = cImageView[0].getTop() + (newDy[0] - preDy[0]);
                    imgW = dx + cImageView[0].getWidth();
                    imgH = dy + cImageView[0].getHeight();
                    cImageView[0].layout(dx, dy, imgW, imgH);
                    // 画像タップ位置に基づき、パラメータ値を生成（線形補間）
                    float nume_apt=(float)(newDx[0]-min_x[0]);//分子
                    float deno_apt=(float)(max_x[0]-min_x[0]);//分母
                    float tilt_apt=-50;//傾き
                    float inter_apt=100;//切片
                    float nume_cav=(float)(newDy[0]-min_y[0]);//分子
                    float deno_cav=(float)(max_y[0]-min_y[0]);//分母
                    float tilt_cav=50;//傾き
                    float inter_cav=50;//切片
                    posi_apt = (int)Math.round((tilt_apt*nume_apt/deno_apt+inter_apt));//100~50を表示
                    posi_cav = (int)Math.round((tilt_cav*nume_cav/deno_cav+inter_cav));//50-100を表示
                    // パラメータ値の画面表示
                    String str_apt = "apt=" + posi_apt;
                    textView_apt.setText(str_apt);
                    String str_cav = "cav=" + posi_cav;
                    textView_cav.setText(str_cav);
//                    Log.d("●onTouch●", "ACTION_MOVE: dx=" + dx + ", dy=" + dy);
                }
                // フラッターエリアの処理
                else if(tap_area == 1) {
                    // 画像タップ位置を決定
                    dx = cImageView[1].getLeft() + (newDx[1] - preDx[1]);
                    dy = cImageView[1].getTop() + (newDy[1] - preDy[1]);
                    imgW = dx + cImageView[1].getWidth();
                    imgH = dy + cImageView[1].getHeight();
                    cImageView[1].layout(dx, dy, imgW, imgH);
                    // 画像タップ位置に基づき、パラメータ値を生成（線形補間）
                    float nume_flt=(float)(newDx[1]-min_x[1]);//分子
                    float deno_flt=(float)(max_x[1]-min_x[1]);//分母
                    float tilt_flt=10;//傾き
                    float inter_flt=0;//切片
                    posi_flt = (int)Math.round((tilt_flt*nume_flt/deno_flt+inter_flt));//0~10を表示
                    // パラメータ値の画面表示
                    String str_flt = "flt=" + posi_flt;
                    textView_flt.setText(str_flt);
                }
                // アタックエリアの処理
                else if(tap_area == 2) {
                    // 画像タップ位置を決定
                    dx = cImageView[2].getLeft() + (newDx[2] - preDx[2]);
                    dy = cImageView[2].getTop() + (newDy[2] - preDy[2]);
                    imgW = dx + cImageView[2].getWidth();
                    imgH = dy + cImageView[2].getHeight();
                    cImageView[2].layout(dx, dy, imgW, imgH);
                    // 画像タップ位置に基づき、パラメータ値を生成（線形補間）
                    float nume_atk=(float)(newDx[2]-min_x[2]);//分子
                    float deno_atk=(float)(max_x[2]-min_x[2]);//分母
                    float tilt_atk=10;//傾き
                    float inter_atk=0;//切片
                    posi_atk = (int)Math.round((tilt_atk*nume_atk/deno_atk+inter_atk));//0~10を表示
                    // パラメータ値の画面表示
                    String str_atk = "atk=" + posi_atk;
                    textView_atk.setText(str_atk);
                }
                break;
            default:
                break;
        }
        // タッチした位置を古い位置とする
        // tap_area = -1or3は、アイコン座標の移動処理はないので下記処理は不要。
        if(tap_area == 0) {
            preDx[0] = newDx[0];
            preDy[0] = newDy[0];
        }
        else if(tap_area == 1) {
            preDx[1] = newDx[1];
            preDy[1] = newDy[1];
        }
        else if(tap_area == 2) {
            preDx[2] = newDx[2];
            preDy[2] = newDy[2];
        }

        // UDP送信スレッド
        new Thread(new Runnable() {
            public void run() {
                try {
                    // ソケットオープン
                    DatagramSocket sendUdpSocket = new DatagramSocket();
                    InetAddress IPAddress = InetAddress.getByName(“hogehoge");
                    int port = hogehoge;//ポート番号
                    // 送信フォーム：apt,cav,flt
                    String[] s = new String[5];
                    s[0] = String.valueOf(posi_apt);
                    s[1] = String.valueOf(posi_cav);
                    s[2] = String.valueOf(posi_flt);
                    s[3] = String.valueOf(posi_atk);
                    s[4] = String.valueOf(posi_oct);
                    String str = s[0] + "," + s[1]+ "," + s[2] + "," + s[3] + "," + s[4];
                    byte[] sendData = str.getBytes("UTF-8");

                    // 送信先と送信データを設定 
                    DatagramPacket sendPacket = new DatagramPacket(
                            sendData, sendData.length, IPAddress, port);
                    // テキストデータを送信
                    sendUdpSocket.send(sendPacket);
                    // ソケットを閉じる　
                    sendUdpSocket.close();

                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }).start();
        // 以上、UDP送信
        return true;
    }
}
```

■PC側のプログラムのソースコード
```c:udp_receive.cpp(winapi)
//参照サイト①：https://www.wabiapp.com/WabiSampleSource/windows/udp_server.html
//参照サイト②：https://www.kana-soft.com/tech/sample_0004.htm
//注意：▲部分はUDP処理と無関係なので、皆様の仕様に合わせて記述下さい。

//一般的なヘッダー
#include <windows.h>
#include <windowsX.h>
#include <stdio.h>
//▲その他、必要に応じて

//UDP関連
#pragma comment( lib, "ws2_32.lib" )//ライブラリ
#define WM_WINSOCKEVENT ( WM_USER + 100 )// WinSockからのイベント

//関数プロトタイプ、変数
static LRESULT CALLBACK	SoundProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
static void InitDialog( HWND hDlg );//▲
static HWND AppWnd;//▲アプリケーションのウインドウハンドル
static SOCKET oSocket;//UDP関連
static float udp_apt, udp_cav;//UDP受信するパラメータ
//▲その他、必要に応じて

int WINAPI	WinMain( HINSTANCE hInst, HINSTANCE hPreInst, LPSTR CmdLine, int show )
{
	//▲
	AppWnd   = NULL;
	DialogBox( hInst, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, (DLGPROC)SoundProc );
	return 0;
}

static LRESULT CALLBACK	SoundProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg ){
	case WM_INITDIALOG://初期化全般
		InitDialog(hDlg);//▲ダイアログボックスの初期化

		//UDP初期化
		WSAData wsaData;
		WSAStartup(MAKEWORD(2, 0), &wsaData);   //(2, 0)はwinsockのバージョン
		//ソケットの生成
		oSocket = socket(AF_INET, SOCK_DGRAM, 0);  //AF_INETはIPv4、SOCK_DGRAMはUDP通信
		// ソケットを非同期にする
		WSAAsyncSelect(oSocket, hDlg, WM_WINSOCKEVENT, FD_READ | FD_CLOSE);
		// アドレス等格納
		struct sockaddr_in oSockAddr;  //IPv4
		oSockAddr.sin_family = AF_INET;
		oSockAddr.sin_port = htons(hogehoge);   //通信ポート番号設定
		oSockAddr.sin_addr.S_un.S_addr = INADDR_ANY; // INADDR_ANY：全アドレス受信
		// バインド
		::bind(oSocket, (struct sockaddr*)&oSockAddr, sizeof(oSockAddr));
		OutputDebugString("hogehoge");
		break;

	case WM_WINSOCKEVENT://UDPデータ受信
	{
		switch (WSAGETSELECTEVENT(lParam)) {
		case FD_READ:
		{
			struct sockaddr_in oFromAddr;
			int sockaddr_in_size = sizeof(struct sockaddr_in);
			CHAR szData[30];//Android側からの単位送信長は30キャラ未満
			//受信
			::recvfrom(
				oSocket
				, (char*)szData
				, sizeof(szData) - 1
				, 0
				, (struct sockaddr*)&oFromAddr
				, &sockaddr_in_size
				);
			//カンマ区切りの受信データを変数にストア
			//受信データは、[数値(apt),数値(cav),数値(flt)･･･]の形式で受信
			sscanf(szData, "%f ,%f ,%f ,%f ,%f", &udp_apt, &udp_cav, &udp_flt, &udp_atk, &udp_oct);
			//apertureによる華やかさの制御
			float apt, cav;//いずれも50～100の範囲
			apt = (-0.02*udp_apt + 2)*2;//0～2の範囲
			synth.midi_aperture_event(apt);//音色制御処理のコール
			//cavityによる華やかさの制御
			cav = -0.02*udp_cav + 4;//2～3の範囲
			synth.midi_cavity_event(cav);//音色制御処理のコール
			// フラッター制御
			float flt;
			flt = udp_flt*0.1;//udp_flt：0～10　→　fltゲイン：0～1
			synth.midi_flutter_event(flt);
			// アタック制御
			float atk;
			atk = udp_atk*0.8;//udp_atk：0～10 → 0～8
			synth.midi_attack_event(atk);
			// オクターブ制御
			float oct;
			oct = udp_oct;//udp_ock：0/1
			synth.midi_octave_event(oct);
//			OutputDebugString(szData);//★受信データの表示
		}
		break;
		}
	}
	break;
	//▲その他処理は必要に応じてcase文で追加（ダイアログボックスの制御など）
	default:
		break;
	}
	return FALSE;
}
```

■動作結果
【Android側】
・下記スクリーンショットのような画面が表示されます。
![Screenshot_20220608-104128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659855/c2c3ada1-512e-2fe7-ebb8-5304edd3ef65.png)
・下記リンク先のYouTube動画のように、太陽アイコンや舌アイコンなどを
　タップして動かした場合、画面のapt、cav、fltなどの数値が変化すればOKです。
　　※YouTube動画リンク先：**https://youtu.be/_rWSoXfOAH0**

【PC側】　
・注意：Android（スマホ）とPCのWiFiをONにして下さい。
・送信確認ツール（Wireshark）を起動し、上記通りAndroidを
　タップするとUDP送信ログが表示されます。
・winapiコードの「★受信データの表示」の行のコメントアウトを
　外し、各種アイコンをタップして動かすと、
　VisualStudioの出力ウインドウに、下記のような表示が出ればOKです。
　表示例：90,95,3,5,0ﾌﾌﾌﾌﾌﾌﾌﾌﾌ88,90,0,1,1,ﾌﾌﾌﾌﾌﾌﾌﾌﾌ
・あとは、取得した数値(90等)を使って、各自が作成された音処理系
　に渡せば（音色はともかく）同じような動作が実現できるはずです。
・通信不良の場合、IPaddrやポート番号（hogehogeと記載した部分）
　の設定ミス、WiFi未接続などが原因と思われます。


■今後の課題
winapi側（含む音処理）すべてをAndroid側にJNIベースで集約していく予定です。