Re: [linux-minidisc] netmd/netmdcli: download support for any .wav file containing pcm audio
Am 01.01.2014 23:30, schrieb Michael Karcher:
The only valid combinations are
PCM -> SP
LP2 -> LP2
LP4 -> LP4
I don't remember whether PCM -> SP Mono support is consistently
implemented in all NetMD devices.
Regards,
Michael Karcher
O.K., i added a function examining the fmt chunk and set correct
wireformat/diskformat values btw. if byte order conversion is needed.
Netmd download should work now for all supported audio files.
I also added pcm mono (8 bit) -> Atrac SP mono.
I don't know if this works, needs some testing.
I do not have any LP4 tracks, this needs some testing, too.
Thomas
P.S.: Apply this patch after the other 2.
>From c0380ed5bb6dc01b3e6930a4d65d45e04ecad609 Mon Sep 17 00:00:00 2001
From: Thomas Arp <manner.moe@gmx.de>
Date: Thu, 2 Jan 2014 22:40:08 +0100
Subject: [PATCH 3/3] netmdcli: implemented netmd download for all supported
audio formats
---
netmdcli/netmdcli.c | 78 ++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 65 insertions(+), 13 deletions(-)
diff --git a/netmdcli/netmdcli.c b/netmdcli/netmdcli.c
index fb54289..e58c35e 100644
--- a/netmdcli/netmdcli.c
+++ b/netmdcli/netmdcli.c
@@ -173,6 +173,11 @@ static inline unsigned int leword32(const unsigned char * c)
return c[3]*16777216+c[2]*65536+c[1]*256+c[0];
}
+static inline unsigned int leword16(const unsigned char * c)
+{
+ return c[1]*256+c[0];
+}
+
static int wav_data_position(const char * data, size_t len)
{
int pos = -1, i = 0;
@@ -181,13 +186,55 @@ static int wav_data_position(const char * data, size_t len)
if(i >= len-4) // break at end of data
break;
- if(strcmp("data", data+i) == 0)
+ if(strncmp("data", data+i, 4) == 0)
pos = i;
i+=2;
}
return pos;
}
+static int audio_supported(const char * file, netmd_wireformat * wireformat, unsigned int * discformat, int * conversion)
+{
+ if(strncmp("RIFF", file, 4) != 0 || strncmp("WAVE", file+8, 4) != 0 || strncmp("fmt ", file+12, 4) != 0)
+ return 0; /* no valid WAVE file or fmt chunk missing*/
+
+ if(leword16(file+20) == 1) /* PCM */
+ {
+ *conversion = 1; /* need byte order conversion for pcm raw data*/
+ *wireformat = NETMD_WIREFORMAT_PCM;
+ if(leword32(file+24) != 44100) /* sample rate */
+ return 0;
+ if(leword16(file+22) == 1 && leword16(file+34) == 8) /* mono, 8bit */
+ *discformat = NETMD_DISKFORMAT_SP_MONO;
+ else if(leword16(file+22) == 2 && leword16(file+34) == 16) /* stereo, 16 bit */
+ *discformat = NETMD_DISKFORMAT_SP_STEREO;
+ else
+ return 0;
+ return 1;
+ }
+
+ if(leword16(file+20) == NETMD_RIFF_FORMAT_TAG_ATRAC3) /* ATRAC3 */
+ {
+ *conversion = 0; /* byte order conversion not needed */
+ if(leword32(file+24) != 44100) /* sample rate */
+ return 0;
+ if(leword16(file+32) == 384) /* data block size LP2 */
+ {
+ *wireformat = NETMD_WIREFORMAT_LP2;
+ *discformat = NETMD_DISKFORMAT_LP2;
+ }
+ else if(leword16(file+32) == 192) /* data block size LP4 */
+ {
+ *wireformat = NETMD_WIREFORMAT_LP4;
+ *discformat = NETMD_DISKFORMAT_LP4;
+ }
+ else
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
int main(int argc, char* argv[])
{
netmd_dev_handle* devh;
@@ -467,10 +514,10 @@ int main(int argc, char* argv[])
char title[256] = {0};
size_t frames;
- int data_position, audio_data_position, audio_data_size, i, file_valid = 0;
+ int data_position, audio_data_position, audio_data_size, i, need_conversion = 1, file_valid = 0;
unsigned char * audio_data;
- netmd_wireformat wireformat = NETMD_WIREFORMAT_PCM;
- unsigned char discformat = NETMD_DISKFORMAT_SP_STEREO;
+ netmd_wireformat wireformat;
+ unsigned char discformat;
/* read source */
stat(argv[2], &stat_buf);
@@ -480,18 +527,20 @@ int main(int argc, char* argv[])
fread(data, data_size, 1, f);
fclose(f);
- /* TODO: check file for codec, PCM (16 bit, 44100 Hz, stereo) should work correctly*/
- if((data_position = wav_data_position((char *)data, data_size)) <= 0)
+ file_valid = audio_supported(data, &wireformat, &discformat, &need_conversion);
+ data_position = wav_data_position(data, data_size);
+
+ if(!file_valid || !data_position)
{
- puts("Error: invalid audio file, cannot find data header position");
+ puts("Error: audio file not supported");
free(data);
+ file_valid = 0;
}
else
{
audio_data_position = data_position+8;
audio_data = data+audio_data_position;
audio_data_size = leword32(data+(data_position+4));
- file_valid = 1;
}
if(file_valid)
@@ -554,12 +603,15 @@ int main(int argc, char* argv[])
error = netmd_secure_setup_download(devh, contentid, kek, sessionkey);
puts(netmd_strerror(error));
- /* audio data byte order conversion, .wav files are little endian, need big endian for pcm raw data*/
- for(i = 0; i < audio_data_size; i+=2)
+ /* audio data byte order conversion */
+ if(need_conversion)
{
- unsigned char first = audio_data[i];
- audio_data[i] = audio_data[i+1];
- audio_data[i+1] = first;
+ for(i = 0; i < audio_data_size; i+=2)
+ {
+ unsigned char first = audio_data[i];
+ audio_data[i] = audio_data[i+1];
+ audio_data[i+1] = first;
+ }
}
/* netmd_prepare_packets() sets correct number of frames depending on the wire format */
--
1.7.10.4