How to use the "Shine-MP3-Encoder-on-AS3-Alchemy"? - audio

I was trying to convert wav to mp3 in my actionscript project, and I was glad to find the https://github.com/phillockwood/Shine-MP3-Encoder-on-AS3-Alchemy
but my actionscript knowledge is so limited that I don't know how to use it in my project.
In my project, the function as follow, convert byteArray data into wav format, and I need to convert the wav into mp3. I know use th Shine-MP3-Encoder can do this job, but I just don't know where to place it in my project, and how to its function ...who can help me out ? I do do appreciate it~~
public static function convertToWav(soundBytes:ByteArray, sampleRate:int):ByteArray {
var data:ByteArray = new ByteArray();
data.endian = Endian.LITTLE_ENDIAN;
var numBytes:uint = soundBytes.length / 2; // soundBytes are 32bit floats, we are storing 16bit integers
var numChannels:int = 1;
var bitsPerSample:int = 16;
// The following is from https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
data.writeUTFBytes("RIFF"); // ChunkID
data.writeUnsignedInt(36 + numBytes); // ChunkSize
data.writeUTFBytes("WAVE"); // Format
data.writeUTFBytes("fmt "); // Subchunk1ID
data.writeUnsignedInt(16); // Subchunk1Size // 16 for PCM
data.writeShort(1); // AudioFormat 1 Mono, 2 Stereo (Microphone is mono)
data.writeShort(numChannels); // NumChannels
data.writeUnsignedInt(sampleRate); // SampleRate
data.writeUnsignedInt(sampleRate * numChannels * bitsPerSample/8); // ByteRate
data.writeShort(numChannels * bitsPerSample/8); // BlockAlign
data.writeShort(bitsPerSample); // BitsPerSample
data.writeUTFBytes("data"); // Subchunk2ID
data.writeUnsignedInt(numBytes); // Subchunk2Size
soundBytes.position = 0;
while(soundBytes.bytesAvailable > 0) {
var sample:Number = soundBytes.readFloat(); // The sample is stored as a sine wave, -1 to 1
var val:int = sample * 32768; // Convert to a 16bit integer
data.writeShort(val);
}
return data;
}

I did this:
Use (ghostcat.media.WAVWriter) to convert a sound bytearray to a wav
Use shine to conver this wav bytearray to an mp3 file
Look up that WAVWriter plugin, that made things really easy for me

you can use this example with the "encodeClicked ()" function
https://github.com/cyrildiagne/Shine-MP3-Encoder-on-AS3-Alchemy/blob/master/src/fr/kikko/test/ShineMP3EncoderTest.as

Related

TarsosDSP Pitch Detection from .wav file. And the result frequency is always less than half

I'm trying to use TarsosDSP library to detect pitch from a .wav file, and the result of frequency is always less than half.
Here is my code.
public class Main {
public static void main(String[] args){
try{
float sampleRate = 44100;
int audioBufferSize = 2048;
int bufferOverlap = 0;
//Create an AudioInputStream from my .wav file
URL soundURL = Main.class.getResource("/DetectPicthFromWav/329.wav");
AudioInputStream stream = AudioSystem.getAudioInputStream(soundURL);
//Convert into TarsosDSP API
JVMAudioInputStream audioStream = new JVMAudioInputStream(stream);
AudioDispatcher dispatcher = new AudioDispatcher(audioStream, audioBufferSize, bufferOverlap);
MyPitchDetector myPitchDetector = new MyPitchDetector();
dispatcher.addAudioProcessor(new PitchProcessor(PitchEstimationAlgorithm.YIN, sampleRate, audioBufferSize, myPitchDetector));
dispatcher.run();
}
catch(FileNotFoundException fne){fne.printStackTrace();}
catch(UnsupportedAudioFileException uafe){uafe.printStackTrace();}
catch(IOException ie){ie.printStackTrace();}
}
}
class MyPitchDetector implements PitchDetectionHandler{
//Here the result of pitch is always less than half.
#Override
public void handlePitch(PitchDetectionResult pitchDetectionResult,
AudioEvent audioEvent) {
if(pitchDetectionResult.getPitch() != -1){
double timeStamp = audioEvent.getTimeStamp();
float pitch = pitchDetectionResult.getPitch();
float probability = pitchDetectionResult.getProbability();
double rms = audioEvent.getRMS() * 100;
String message = String.format("Pitch detected at %.2fs: %.2fHz ( %.2f probability, RMS: %.5f )\n", timeStamp,pitch,probability,rms);
System.out.println(message);
}
}
}
The 329.wav file is generated from http://onlinetonegenerator.com/ website with 329Hz.
I don't know why the result pitch is always 164.5Hz. Is there any problem in my code?
Well I don't know what methods you are using, but by looking at how the frequency is exactly halved, it could be a problem of wrong sample rate being set?
Most operations assume an initial sample rate when the signal was sampled, maybe you've passed it as an argument (or its default value is) half that?
I just had the same problem with TarsosDSP on Android. For me the answer was that the file from http://onlinetonegenerator.com/ has 32-bit samples instead of 16-bit, which appears to be the default. Relevant code:
AssetFileDescriptor afd = getAssets().openFd("440.wav"); // 440Hz sine wave
InputStream is = afd.createInputStream();
TarsosDSPAudioFormat audioFormat = new TarsosDSPAudioFormat(
/* sample rate */ 44100,
/* HERE sample size in bits */ 32,
/* number of channels */ 1,
/* signed/unsigned data */ true,
/* big-endian byte order */ false
);
AudioDispatcher dispatcher = new AudioDispatcher(new UniversalAudioInputStream(is, audioFormat), 2048, 0);
PitchDetectionHandler pdh = ...
AudioProcessor p = new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 44100, 2048, pdh);
dispatcher.addAudioProcessor(p);
new Thread(dispatcher, "Audio Dispatcher").start();

Set volume to mp3 stream using NAudio

Here in this code,
I am using NAudio and Lame to convert wav file to mp3 stream and I am getting mp3 stream output without any issues. But apart from this I also want to set volume to the final mp3 stream. Any help is greatly appreciated.
public byte[] ConvertWavToMP3(byte[] bt, uint bitrate)
{
MemoryStream ms = new MemoryStream(bt);
ms.Seek(0, SeekOrigin.Begin);
var ws = new WaveFileReader(ms);
byte[] wavdata = null;
using (MemoryStream wavstrm = new MemoryStream())
using (WaveFileWriter wavwri = new WaveFileWriter(wavstrm, ws.WaveFormat))
{
ws.CopyTo(wavwri);
wavdata = wavstrm.ToArray();
}
WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(ws.WaveFormat.SampleRate, ws.WaveFormat.BitsPerSample, ws.WaveFormat.Channels);
Yeti.Lame.BE_CONFIG beconf = new Yeti.Lame.BE_CONFIG(fmt, bitrate);
using (MemoryStream mp3strm = new MemoryStream())
using (Mp3Writer mp3wri = new Mp3Writer(mp3strm, fmt, beconf))
{
mp3wri.Write(wavdata, 0, wavdata.Length);
byte[] mp3data = mp3strm.ToArray();
return mp3data;
}
}
You can use AudioFileReader which will give you a Volume property you can adjust (1.0 is full scale). It will also turn the audio into an ISampleProvider with IEEE float samples, but I think LAME accepts IEEE float, otherwise use SampleToWaveProvider16 to get back down to 16 bit integer samples.

Read a PNG image using Haxe

Using the Haxe programming language, is there any cross-platform way to read a PNG image, and get the pixel data from the image?
I have a file called stuff.png, and I want to obtain an array of RGB values from the image (as an integer array).
Here's an example usage of the Haxe format library to read a PNG file. You need -lib format in your compiler args / build.hxml:
function readPixels(file:String):{data:Bytes, width:Int, height:Int} {
var handle = sys.io.File.read(file, true);
var d = new format.png.Reader(handle).read();
var hdr = format.png.Tools.getHeader(d);
var ret = {
data:format.png.Tools.extract32(d),
width:hdr.width,
height:hdr.height
};
handle.close();
return ret;
}
Here's an example of how to get ARGB pixel data from the above:
public static function main() {
if (Sys.args().length == 0) {
trace('usage: PNGReader <filename>');
Sys.exit(1);
}
var filename = Sys.args()[0];
var pixels = readPixels(filename);
for (y in 0...pixels.height) {
for (x in 0...pixels.width) {
var p = pixels.data.getInt32(4*(x+y*pixels.width));
// ARGB, each 0-255
var a:Int = p>>>24;
var r:Int = (p>>>16)&0xff;
var g:Int = (p>>>8)&0xff;
var b:Int = (p)&0xff;
// Or, AARRGGBB in hex:
var hex:String = StringTools.hex(p,8);
trace('${ x },${ y }: ${ a },${ r },${ g },${ b } - ${ StringTools.hex(p,8) }');
}
}
You can always access the pixel data with BitmapData.getPixels/BitmapData.setPixels.
If you are using haXe NME, you can use Assets.getBitmapData() to load an asset image file.
If you want to load images from network, then you can use Loader class, it can asynchronous loading remote images, but in flash please mind the cross-domain issue.
For more generic ByteArray -> BitmapData conversion, use following code:
var ldr = new Loader();
ldr.loadBytes(cast(byteArray)); // bytearray contains raw image data
var dp: DisplayObject = ldr.content; // actually ontent should be of Bitmap class
var bitmapData = new BitmapData(Std.int(dp.width), Std.int(dp.height), true, 0);
bitmapData.draw(dp);

Save an RGB24 sample to bitmap

I'm using Windows Media Foundation to do some messing around with my webcam. I've been able to successfully retrieve a data sample from the webcam and identify that the format is RGB24. Now I'd like to save a single frame as a bitmap. A small snippet of the code I'm using to read a sample from the webcam is below.
IMFSample *pSample = NULL;
hr = pReader->ReadSample(
MF_SOURCE_READER_ANY_STREAM, // Stream index.
0, // Flags.
&streamIndex, // Receives the actual stream index.
&flags, // Receives status flags.
&llTimeStamp, // Receives the time stamp.
&pSample // Receives the sample or NULL.
);
So once I've got pSample populated with an IMFSample how can I save it as a bitmap?
Below is the code snippet I used to save a bitmap from an IMFSample. I've taken a lot of shortcuts and I'm pretty sure I'm only able to get away with doing things this way because my webcam defaults to returning an RGB24 stream and also a 640 x 480 pixel buffer which means there's no striping to worry about in pData.
hr = pReader->ReadSample(
MF_SOURCE_READER_ANY_STREAM, // Stream index.
0, // Flags.
&streamIndex, // Receives the actual stream index.
&flags, // Receives status flags.
&llTimeStamp, // Receives the time stamp.
&pSample // Receives the sample or NULL.
);
wprintf(L"Stream %d (%I64d)\n", streamIndex, llTimeStamp);
HANDLE file;
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER fileInfo;
DWORD write = 0;
file = CreateFile(L"sample.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); //Sets up the new bmp to be written to
fileHeader.bfType = 19778; //Sets our type to BM or bmp
fileHeader.bfSize = sizeof(fileHeader.bfOffBits) + sizeof(RGBTRIPLE); //Sets the size equal to the size of the header struct
fileHeader.bfReserved1 = 0; //sets the reserves to 0
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //Sets offbits equal to the size of file and info header
fileInfo.biSize = sizeof(BITMAPINFOHEADER);
fileInfo.biWidth = 640;
fileInfo.biHeight = 480;
fileInfo.biPlanes = 1;
fileInfo.biBitCount = 24;
fileInfo.biCompression = BI_RGB;
fileInfo.biSizeImage = 640 * 480 * (24/8);
fileInfo.biXPelsPerMeter = 2400;
fileInfo.biYPelsPerMeter = 2400;
fileInfo.biClrImportant = 0;
fileInfo.biClrUsed = 0;
WriteFile(file,&fileHeader,sizeof(fileHeader),&write,NULL);
WriteFile(file,&fileInfo,sizeof(fileInfo),&write,NULL);
IMFMediaBuffer *mediaBuffer = NULL;
BYTE *pData = NULL;
pSample->ConvertToContiguousBuffer(&mediaBuffer);
hr = mediaBuffer->Lock(&pData, NULL, NULL);
WriteFile(file, pData, fileInfo.biSizeImage, &write, NULL);
CloseHandle(file);
mediaBuffer->Unlock();
I've included a bit of a discussion here.

Simplest way to capture raw audio from audio input for real time processing on a mac

What is the simplest way to capture audio from the built in audio input and be able to read the raw sampled values (as in a .wav) in real time as they come in when requested, like reading from a socket.
Hopefully code that uses one of Apple's frameworks (Audio Queues). Documentation is not very clear, and what I need is very basic.
Try the AudioQueue Framework for this. You mainly have to perform 3 steps:
setup an audio format how to sample the incoming analog audio
start a new recording AudioQueue with AudioQueueNewInput()
Register a callback routine which handles the incoming audio data packages
In step 3 you have a chance to analyze the incoming audio data with AudioQueueGetProperty()
It's roughly like this:
static void HandleAudioCallback (void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc) {
// Here you examine your audio data
}
static void StartRecording() {
// now let's start the recording
AudioQueueNewInput (&aqData.mDataFormat, // The sampling format how to record
HandleAudioCallback, // Your callback routine
&aqData, // e.g. AudioStreamBasicDescription
NULL,
kCFRunLoopCommonModes,
0,
&aqData.mQueue); // Your fresh created AudioQueue
AudioQueueStart(aqData.mQueue,
NULL);
}
I suggest the Apple AudioQueue Services Programming Guide for detailled information about how to start and stop the AudioQueue and how to setup correctly all ther required objects.
You may also have a closer look into Apple's demo prog SpeakHere. But this is IMHO a bit confusing to start with.
It depends how ' real-time ' you need it
if you need it very crisp, go down right at the bottom level and use audio units. that means setting up an INPUT callback. remember, when this fires you need to allocate your own buffers and then request the audio from the microphone.
ie don't get fooled by the presence of a buffer pointer in the parameters... it is only there because Apple are using the same function declaration for the input and render callbacks.
here is a paste out of one of my projects:
OSStatus dataArrivedFromMic(
void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * dummy_notused )
{
OSStatus status;
RemoteIOAudioUnit* unitClass = (RemoteIOAudioUnit *)inRefCon;
AudioComponentInstance myUnit = unitClass.myAudioUnit;
AudioBufferList ioData;
{
int kNumChannels = 1; // one channel...
enum {
kMono = 1,
kStereo = 2
};
ioData.mNumberBuffers = kNumChannels;
for (int i = 0; i < kNumChannels; i++)
{
int bytesNeeded = inNumberFrames * sizeof( Float32 );
ioData.mBuffers[i].mNumberChannels = kMono;
ioData.mBuffers[i].mDataByteSize = bytesNeeded;
ioData.mBuffers[i].mData = malloc( bytesNeeded );
}
}
// actually GET the data that arrived
status = AudioUnitRender( (void *)myUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
& ioData );
// take MONO from mic
const int channel = 0;
Float32 * outBuffer = (Float32 *) ioData.mBuffers[channel].mData;
// get a handle to our game object
static KPRing* kpRing = nil;
if ( ! kpRing )
{
//AppDelegate * appDelegate = [UIApplication sharedApplication].delegate;
kpRing = [Game singleton].kpRing;
assert( kpRing );
}
// ... and send it the data we just got from the mic
[ kpRing floatsArrivedFromMic: outBuffer
count: inNumberFrames ];
return status;
}

Resources