Binary data write wav file sd card

binary data write wav file sd card

Hello, I want to receive binary data through TCP socket communication and save it as a wav file on the SD card.

It is possible to save, but even if you directly run the file in the SD card, it cannot be played back. Please let me know what is wrong.

Board used: arduino mkr zero, arduino mkr ethernet shild

=========================> my arduino code (server) <==========================

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

File myFile;

byte mac[ ] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02
};

IPAddress ip(172, 30, 1, 150);
IPAddress myDns(168, 126, 63, 1);
IPAddress gateway(172, 30, 1, 254);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(6000);

boolean gotAMessage = false;
void setup() {
  Ethernet.init(5);
  // Open serial communications and wait for port to open:

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start the Ethernet connection:
  Serial.println("Trying to get an IP address using DHCP");

  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      while (true) {
        delay(1); // do nothing, no point running without Ethernet hardware
      }
    }

    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }

    // initialize the Ethernet device not using DHCP:
    Ethernet.begin(mac, ip, myDns, gateway, subnet);
  }

  // print your local IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());

  // start listening for clients
  server.begin();

  if (!SD.begin()) {
    Serial.println("SD initialization failed!");
    while (1);
  } else {
    Serial.println("SD initialization success!");
  }
}

void loop() {
  delay(1);
  EthernetClient client = server.available();

  if (client) {
    if (!gotAMessage) {
      Serial.println("We have a new client");
      gotAMessage = true;
    }

    Serial.print("Writing voice.wav...");
    myFile = SD.open("voice.wav", FILE_WRITE);

    while (client.available()) {
        Serial.print("read >> ");
        Serial.print(client.read());
        Serial.println();
        myFile.write(client.read());
    }

    Serial.print("Writing voice.wav...");
    Serial.print("\n");

    // close the file:
    myFile.close();

    Serial.println("done.");
    // echo the bytes to the server as well:

    Ethernet.maintain();
  }
}

=========================> my java code (client) <==========================

@Transactional(rollbackFor = Exception.class)
    public boolean sendVoice(CommandMap params, MultipartFile file, Locale locale) throws RequestResolveException {
        if(file != null) {
        	UserInfo user = getUserInfo();
    		params.put("svcKey", user.getSvcKey());
    		if(params.isEmptyValue("svcKey")){
    			throw new RequestResolveException(ErrorCode.INVALID_PARAMETER, getMessage("common.msg.notfound", locale, null));
    		}
        	if(params.isEmptyValue("skbKey")) {
        		throw new RequestResolveException(ErrorCode.INVALID_PARAMETER, getMessage("common.msg.notfound", locale, null));
        	}
        	
    		int port = Integer.parseInt("6000");
    		String serverIp = "172.30.1.51";
    		
    		byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    		int readBytes;
    		long fileSize = file.getSize();
    		long totalReadBytes = 0;
    		double startTime = 0;
    		
    		Socket socket = null;
    		FileInputStream fis = null;
    		OutputStream os = null;
    		
    		try {
    			fis = (FileInputStream) file.getInputStream();
    			socket = new Socket(serverIp, port);
    			if(!socket.isConnected()){
    				throw new RequestResolveException(ErrorCode.INVALID_PARAMETER, getMessage("sk.api.msg.fail", locale, null));
    			}
    			os = socket.getOutputStream();
    			while ((readBytes = fis.read(buffer)) > 0) {
    				os.write(buffer, 0, readBytes);
    				totalReadBytes += readBytes;
    				System.out.println("In progress: " + totalReadBytes + "/" + fileSize + " Byte(s) (" + (totalReadBytes * 100 / fileSize) + " %)");
    			}
    		} catch (UnknownHostException e) {
    			e.printStackTrace();
    			throw new RequestResolveException(ErrorCode.INVALID_PARAMETER, getMessage("sk.api.msg.fail", locale, null));
    		} catch (IOException e) {
    			e.printStackTrace();
    			throw new RequestResolveException(ErrorCode.INVALID_PARAMETER, getMessage("sk.api.msg.fail", locale, null));
    		} finally {
    			try { if(fis != null) fis.close(); } catch (Exception e) { e.printStackTrace(); }
    			try { if(os != null) os.close(); } catch (Exception e) { e.printStackTrace(); }
    			try { if(socket != null) socket.close(); } catch (Exception e) { e.printStackTrace(); }
    		}
        		
        } else {
            throw new RequestResolveException(ErrorCode.EMPTY_PARAMETER, getMessage("common.msg.requirevalue", locale, "common.file"));
        }
        return true;
    }

You write one Byte to the serial interface, the other into the open file. This way only half of the file's content is saved into the file on the SD card, the other half is printed to the serial interface.

Thank you for answer.

=============== edit code ==================
     myFile = SD.open("voice.wav", FILE_WRITE);
     int readBytes = 0;
     while (client.available()) {
         myFile.write(client.read());
         readBytes += 1;
     }
     Serial.print(readBytes);
=============== edit code ==================

After editing,
I checked the number of bytes to see if it was recorded the same, and saved it, but when I actually opened it, it was saved as a file that cannot be played.

I looked at the properties and there is no length, no bitrate.

Have you added the wav header to what you save?
This header needs to contain the length and sample rate of the WAV file, so you either write those in advance of any data, or once the file is written to the SD card and you know the size of the data copy the data file into a new file with the header.

Search the net for information about the WAV format header.

@leejunhyeong1218 you may find it useful to use a hex editor to view the contents of the original file and compare with the file you have written to the SD card.

That would help you determine if you have dropped a few bytes along the way, or if you are missing large sections of data.

Does that mean the sizes of the original file and the save file were identical? If yes, it would be interesting in what bytes the content differ as markd833 already mentioned.

Can you expand on this? Where is the binary data coming from? Is it already a WAV file that is being sent by file transfer for example. Or is it maybe raw amplitude data from an audio source?

If it is raw data, then you will need to generate a WAV file header for the data as already suggested.

If it is raw data, then you should be able to import the file into Audacity as a raw file. You would need to know the sample rate and if it was mono/stereo etc but that would quickly give you an idea that what you have captured and saved to the SD card was correct.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.