<job>
<script language="VBScript">
function vbBinaryToArray(bin)
	dim i
	ReDim byteArray(LenB(bin))
	for i=1 to LenB(bin)
		byteArray(i-1)=AscB(MidB(bin, i, 1))
	next
	vbBinaryToArray=byteArray
end function
function vbInputBox(msg, title, def)
	vbInputBox=InputBox(msg, title, def)
end function
</script>
<script language="JavaScript">
// bZ[WvC[ MyVoice
// https://koyama.verse.jp/elecraft/myvoice
// 20230616 koyama88@cameo.plala.or.jp
// ()
// (1) ZbZ[W(^)Đł܂B
// (2) ̉o^A{^ōĐ鉹Ił܂B
// (3) ArduinoUNO/NANO, Digispark, ATtiny85, ATtiny4313, ATmega328PȂǂœ삵܂B
// (4) L^ł鉹bZ[W͎̒gp}CRɂقȂAATtiny85ł͒i1.5bAi3bxłB
//
// (f[^̍쐬)
// (1) AudacityȂǂ̃\tggAp\Rŉ^Awavt@CƂĕۑ܂BX}zŘ^t@CFFMPEGȂǂ̃\tggĕϊ邱Ƃł܂B
// (2) ͂߂ myvoice.wsf _uNbNĉf[^t@C(myvoice.h)܂B
// (3) ^t@C(ZZ.wav) myvoice.wsf ɃhbOhbvƁAf[^t@Cɉf[^L^܂B
// (4) (3)̑JԂƁAf[^t@Cɕ̉o^ł܂BAL^ł鎞Ԃ́uvŁv}CR̗eʂ͈̔͂ƂȂ܂B
// (5) ύXꍇ́A(2)̏蒼܂B
//
// (vȌ)
// ArduinoIDENAmyvoice.ino Jď݂܂B
//
// (g)
// (1) d𓊓ƁA^bZ[WĐ܂BOXCb`ȂƁAXCb`ƂɍĐ܂BXCb`𒷉2ڈȍ~̉Đł܂B

var ws=WScript.CreateObject("WScript.Shell");
var sh =new ActiveXObject("Shell.Application");
var ado=new ActiveXObject("ADODB.Stream");
var fso=new ActiveXObject("Scripting.FileSystemObject");
var folder=fso.GetFile(WScript.ScriptFullName).ParentFolder;

if(WScript.Arguments.length==0){			// _uNbNŋN
	var	myvoice_h=fso.CreateTextFile(folder+"/myvoice.h",true);
	var btn=ws.Popup("f[^܂B낵ł?",0,"f[^",3);
	if(btn==6){													// ͂(Y)Ȃf[^
		var s="// This file contains ADPCM encoded data created by myvoice.wsf\n\n"
		s+="#define MYVOICE\n";
		s+="#define NVOICE 0		// number of voice data\n\n";
		s+="\nconst uint8_t* const Voice[] PROGMEM={};	// pointer of each voice data\n";
		s+="\nuint16_t voicesize[]={};							// size(bytes) of each voice data\n";
		myvoice_h.Write(s);
		myvoice_h.Close();
	}
	WScript.Echo("f[^܂B\nwavt@ChbOhbvĂ");
	WScript.Quit();
}
var filename=WScript.Arguments(0).toLowerCase();
if(!filename.match(/\.wav$/)){
	WScript.Echo("wavt@ChbOhbvĂ");	WScript.Quit();
}else{																// wavt@ChbOhbv
// wavt@Cmyvoice.h쐬 ----------------------------------------------
	var wav=binaryFileToArray(filename);
	var samplebits=wav[16]+wav[17]*256;	// 16 bit
	var format	=wav[20]+wav[21]*256;		// 1 񈳏kPCM
	var ch			=wav[22]+wav[23]*256;		// 1 m
	var rate		=wav[24]+wav[25]*256+wav[26]*65536+wav[27]*16777216;	// 8000 sps
	var wavlen	=wav[40]+wav[41]*256+wav[42]*65536+wav[43]*16777216;	//f[^(bytes)
	if(samplebits!=16){
		WScript.Echo("1Tv16rbgwavt@CpӂĂ");
		WScript.Quit();
	}
	if(format!=1){
		WScript.Echo("񈳏kPCMwavt@CpӂĂ");
		WScript.Quit();
	}
	if(ch!=1){
		WScript.Echo("mwavt@CpӂĂ");
		WScript.Quit();
	}
	if(rate!=8000){
		WScript.Echo("TvOg8000Hzwavt@CpӂĂ");
		WScript.Quit();
	}
	var lastsample=0;											// Output of ADPCM predictor
	var lastindex=0;											// Quantizer step size index
	var j=0;
	var p=0;															// f[^̃|C^(l͐擪)
	var IndexTable=[											// Table of index changes
		[-1,2],															// 16kBPS
		[-1,-1,-1,-1,2,4,6,8],							// 32kBPS
	];
	var StepSizeTable=[										// Quantizer step size lookup table
		7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
		19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
		50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
		130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
		337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
		876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
		2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
		5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
		15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
	];

	var sVoice=readFile(folder+"/myvoice.h").replace(/\r\n/g,"\n");
	var nVoice=parseInt(sVoice.match(/#define\sNVOICE\s(\d+)/)[1]);
//	var nVoice=pointerArray.length;				// ݂̘^̃f[^
	var codesize=0;
	if(sVoice.match(/#define\sCODESIZE\s4/))			codesize=4;	// 32kbps(4-bits * 8ksps)
	else if(sVoice.match(/#define\sCODESIZE\s2/))	codesize=2;	// 16kbps(2-bits * 8ksps)
	if(codesize!=4 && codesize!=2){	// CODESIZEݒȂ
		var btn=ws.Popup("i?\n͂(Y): i(ő1.5b)\n(N): i(ő3b)",0,"f[^",3);
		if(btn==6)	codesize=4;							// ͂(Y)Ȃ32kbps(4-bits * 8ksps)
		else				codesize=2;							// (N)Ȃ16kbps(2-bits * 8ksps)
	}
	// : "".split(",")  [] ł͂Ȃ [""]
	var pointerArray=sVoice.match(/const Voice\[\] PROGMEM=\{(.*)\};/)[1];
	pointerArray=(pointerArray==""?[]:pointerArray.split(","));
	var voicesizeArray=sVoice.match(/voicesize\[\]=\{(.*)\};/)[1];
	voicesizeArray=(voicesizeArray==""?[]:voicesizeArray.split(","));
	var s="// This file contains ADPCM encoded data created by myvoice.wsf\n\n";
	s+="#define CODESIZE "+codesize+"	// 4:4*8ksps=32kbps / 2:2*8ksps=16kbps\n";
	s+="#define NVOICE "+(nVoice+1)+"		// number of voice data\n\n";
	var u=sVoice.match(/const uint8_t Voice\d+\[\] PROGMEM=\{[\s\S]*?\};\n/g);	// ̃f[^
	if(u)	s+=u.join("\n");
	s+="\nconst uint8_t Voice"+nVoice+"[] PROGMEM={	// "+(codesize==4?"dual 4":"quad 2")
			+"-bit ADPCM data from "+fso.getFileName(filename)+"\n";	// VKf[^̒ǉ
	var bytes=0;
	for(var p=44; p<wavlen;){
		if(bytes%8==0)	s+="\t";
		if(codesize==4){										// 32kbps(1Tv4-bit/sample)Ȃ
			var val=wav[p++]|(wav[p++]<<8);
			if(val>=32768)	val-=66636;
			var code=ADPCMEncoder(val)<<4;
			if(p<wavlen){
				val=wav[p++]|(wav[p++]<<8);
				if(val>=32768)	val-=66636;
				code|=ADPCMEncoder(val);
			}
			s+="0x"+("0"+code.toString(16)).slice(-2)+", ";
			if((++bytes)%8==0)	s+="\n";
		}else{															// 16kbps(1Tv2-bit/sample)Ȃ
			var val=wav[p++]|(wav[p++]<<8);		if(val>=32768)	val-=66636;
			var code=ADPCMEncoder(val)<<6;
			if(p<wavlen){
				val=wav[p++]|(wav[p++]<<8);			if(val>=32768)	val-=66636;
				code|=ADPCMEncoder(val)<<4;
				if(p<wavlen){
					val=wav[p++]|(wav[p++]<<8);		if(val>=32768)	val-=66636;
					code|=ADPCMEncoder(val)<<2;
					if(p<wavlen){
						val=wav[p++]|(wav[p++]<<8);	if(val>=32768)	val-=66636;
						code|=ADPCMEncoder(val);
						s+="0x"+("0"+code.toString(16)).slice(-2)+", ";
					}
				}
			}
			if((++bytes)%8==0)	s+="\n";
		}
	}
	s+="};\n";
	s=s.replace(/,\s}/,"}");
	pointerArray.push("Voice"+nVoice);		// Voice0, Voice1, ...
	s+="\nconst uint8_t* const Voice[] PROGMEM={"+pointerArray.join(",")+"};"
			+"	// pointer of each voice data\n";
	voicesizeArray.push(bytes);
	s+="\nuint16_t voicesize[]={"+voicesizeArray.join(",")+"};"
			+"	// size(bytes) of each voice data\n";
	var	myvoice_h=fso.CreateTextFile(folder+"/myvoice.h",true);
	myvoice_h.Write(s);
	myvoice_h.Close();
// ܂ --------------------------------------------------------------------
}
WScript.Echo("ArduinoIDEmyvoice.inoJďłB");

function readFile(fname){
	ado.Type=2;														// Text
	ado.charset="_autodetect_all";
	ado.Open();
	ado.LoadFromFile(fname);
	var text=ado.ReadText(-1);						// adReadAll
	ado.Close();
	return text;
}
function writeFile(fname, text){				// UTF-8Ńt@C̕ۑ
	ado.Type=2;														// Text
//ado.charset="utf-8";									// SHIFT_JIS/utf-8
	ado.Open();
	ado.WriteText(text);									// adWriteLine
	ado.SaveToFile(fname, 2);							// adSaveCreateOverWrite
	ado.Close();
}
function binaryFileToArray(fname){
	ado.Type=1;														// Binary
	ado.Open();
	ado.LoadFromFile(fname);
	var bin=ado.Read();
	ado.Close();
	var array=VbBinaryToArray(bin).toArray();
	array.length--;
	return array;
};
// Original Code for PIC by Rodger Richey, 1-9-96
// This ADPCM routines were obtained from the Interactive Multimedia Association's
// Reference ADPCM algorithm.  This algorithm was first implemented by Intel/DVI.
function ADPCMDecoder(code){
	var predsample=lastsample;					// Restore previous values of predicted sample
	var index=lastindex;								// and quantizer step size index
	var diffq;													// Dequantized predicted difference
// Find quantizer step size from lookup table using index
	var step=StepSizeTable[index];			// Quantizer step size
	if(codesize==4){										// 32kbps(1Tv4-bit/sample)
// Inverse quantize the ADPCM code into a difference using the quantizer step size
		var diffq=step>>3;
		if(code&4)	diffq+=step;
		if(code&2)	diffq+=step>>1;
		if(code&1)	diffq+=step>>2;
// Add the difference to the predicted sample
		if(code&8)	predsample-=diffq;
		else				predsample+=diffq;
// Find new quantizer step size by adding the old index and a table lookup
// using the ADPCM code
		index+=IndexTable[1][code&0x07];
	}else{																// 16kbps(1Tv2-bit/sample)
// Inverse quantize the ADPCM code into a difference using the quantizer step size
		diffq=step>>1;
		if(code&1)	diffq+=step;
// Add the difference to the predicted sample
		if(code&2)	predsample-=diffq;
		else				predsample+=diffq;
// Find new quantizer step size by adding the old index and a table lookup
// using the ADPCM code
		index+=IndexTable[0][code&0x01];
	}
// Check for overflow of the new predicted sample
	if(predsample>32767)				predsample=32767;
	else if(predsample<-32768)	predsample=-32768;
	if(index<0)				index=0;
	else if(index>88)	index=88;
// Save predicted sample for next iteration and quantizer step size index
	lastsample=predsample;	lastindex=index;
	return(predsample);
}
function ADPCMEncoder(sample){
	var code;
	var predsample=lastsample;					// Restore previous values of predicted sample
	var index=lastindex;								// and quantizer step size index
	var diffq=sample-predsample;				// Dequantized predicted difference
	var step=StepSizeTable[index];			// Quantizer step size
	if(codesize==4){										// 32kbps(1Tv4-bit/sample)
		if(diffq>=0)								code=0;
		else{												code=8;		diffq=-diffq;	}
		if(diffq>=step){						code|=4;	diffq-=step;	}
		step>>=1;	if(diffq>=step){	code|=2;	diffq-=step;	}
		step>>=1;	if(diffq>=step)		code|=1;
	}else{															// 16kbps(1Tv2-bit/sample)
		if(diffq>=0)								code=0;
		else{												code=2;		diffq=-diffq;	}
		if(diffq>=step)							code|=1;
	}
	ADPCMDecoder(code);
	return(code);
}
</script>
</job>