LoginSignup
1
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-06-10

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

■Android側のプログラムのソースコード
 (補足)各種アイコン(glitter_icon.png等)や背景画像(bg.jpg)は、pptで作成。

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>
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側のプログラムのソースコード

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
・下記リンク先の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ベースで集約していく予定です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0