ANE中如何调用lame库在iOS平台WAV转换MP3
代码中包含了三个功能,输出sayHello,检测耳机是否插入,MP3转换
OC部分
//
// Main.m
// HelloLib
//
// Created by Darren on 16/3/9.
// Copyright © 2016年 darren. All rights reserved.
//
#import "FlashRuntimeExtensions.h"
#import <AudioToolbox/AudioToolbox.h>
#import "lame.h"
void dispatchMsgEvent(NSString *msg,NSString *code);
void outLog(NSString *msg,NSString *code);
NSString * getStringFromFREObject(FREObject obj);
FREContext eventContext;
lame_t lame;
void outLog(NSString *msg,NSString *code)
{
dispatchMsgEvent(msg,code);
}
void dispatchMsgEvent(NSString *msg,NSString *code)
{
if (eventContext == NULL) {
return;
}
const uint8_t *eventCode = (const uint8_t *)[msg UTF8String];
const uint8_t *msgCode = (const uint8_t *)[code UTF8String];
FREDispatchStatusEventAsync(eventContext, eventCode, msgCode);
}
//将FREObject转成NSString
NSString * getStringFromFREObject(FREObject obj)
{
uint32_t length;
const uint8_t *value;
FREGetObjectAsUTF8(obj, &length, &value);
return [NSString stringWithUTF8String:(const char *)value];
}
//
// wav转换成mp3
//
FREObject wavToMP3(
FREContext ctx,
void* functionData,
uint32_t argc,
FREObject argv[]
)
{
FREObject obj;
outLog(@"log_event_out",@"进入wavToMP3");
NSString *pcmPath = getStringFromFREObject(argv[0]);
if (pcmPath == nil || [pcmPath isEqualToString:@""]) {
return NULL;
}
//获取到document目录
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *mp3Path = [docDir stringByAppendingString:@"/hehe.mp3"];
outLog(@"log_event_out",[NSString stringWithFormat:@"pcm => %@ mp3 => %@",docDir,mp3Path]);
int read,write;
FILE *pcm = fopen([pcmPath cStringUsingEncoding:1], "rb");
fseek(pcm, 4*1024, SEEK_CUR);
FILE *mp3 = fopen([mp3Path cStringUsingEncoding:1], "wb");
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE * 2];
unsigned char mp3_buffer[MP3_SIZE];
@try {
lame = lame_init();
//设置声道
lame_set_num_channels(lame,2);
//设置采样率
lame_set_in_samplerate(lame, 44100);
//压缩比特率
lame_set_brate(lame, 128);
//模式 双声道,单声道,立体声
lame_set_mode(lame, 1);
//品质 0~9 (0最好 9最差)
lame_set_quality(lame, 5);
lame_init_params(lame);
do {
read = fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm);
if (read == 0) {
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
}else{
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
}
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
NSLog(@"转换完成");
}
@catch (NSException *exception) {
outLog(@"log_event_out",[NSString stringWithFormat:@"error ==> %@",[exception debugDescription]]);
}
@finally {
//释放资源
lame_close(lame);
fclose(pcm);
fclose(mp3);
}
uint8_t * reoutPath = (uint8_t *)[mp3Path UTF8String];
FRENewObjectFromUTF8(strlen((const char*)reoutPath), reoutPath, &obj);
return obj;
}
FREObject sayHello(
FREContext ctx,
void* functionData,
uint32_t argc,
FREObject argv[]
)
{
FREObject obj;
uint8_t * value = (uint8_t *)"Hello Adobe air";
FRENewObjectFromUTF8(strlen((const char*)value), value, &obj);
return obj;
}
/**
耳机检测回调
*/
void audioRouteChangeListenerCallback(
void * inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void * inData
)
{
if (inID != kAudioSessionProperty_AudioRouteChange) {
return;
}
CFDictionaryRef routeChangeDic = (CFDictionaryRef)inData;
CFNumberRef routeChangeReasonRef = CFDictionaryGetValue(routeChangeDic, CFSTR(kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue(routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
dispatchMsgEvent(@"AudioSessionRouteChangeReason_OldDeviceUnavailable",@"yes");
}else if(routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable){
dispatchMsgEvent(@"AudioSessionRouteChangeReason_NewDeviceAvailable",@"no");
}
}
/**
初始化耳机检测
*/
FREObject initChectHeadset(
FREContext ctx,
void* functionData,
uint32_t argc,
FREObject argv[]
)
{
eventContext = ctx;
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionSetActive(YES);
AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, nil);
return NULL;
}
void contextInit(
void* extData ,
const uint8_t* ctxType ,
FREContext ctx ,
uint32_t* numFunctionsToSet,
const FRENamedFunction** functionsToSet
)
{
*numFunctionsToSet = 3;
FRENamedFunction *functions = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)* *numFunctionsToSet);
functions[0].name = (const uint8_t*)"sayHello";
functions[0].functionData = NULL;
functions[0].function = &sayHello;
functions[1].name = (const uint8_t *)"initChectHeadset";
functions[1].functionData = NULL;
functions[1].function = &initChectHeadset;
functions[2].name = (const uint8_t *)"wavToMP3";
functions[2].functionData = NULL;
functions[2].function = &wavToMP3;
*functionsToSet = functions;
}
///
///初始化方法
///
void helloInitTest(
void** extDataToSet ,
FREContextInitializer* ctxInitializerToSet,
FREContextFinalizer* ctxFinalizerToSet
)
{
*ctxInitializerToSet = &contextInit;
}
as3代码部分
package com.xd
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.StatusEvent;
import flash.external.ExtensionContext;
public class HelloANE extends EventDispatcher
{
private var ec:ExtensionContext = null;
public static const ID:String = "com.xd.hello";
public function HelloANE(target:IEventDispatcher=null)
{
super(target);
ec = ExtensionContext.createExtensionContext(ID,null);
if(ec){
ec.addEventListener(StatusEvent.STATUS,onStatus);
}
}
/**
* 初始化耳机检测
*/
public function initChectHeadset():void
{
ec.call("initChectHeadset");
}
protected function onStatus(event:StatusEvent):void
{
trace("事件回调 \n"+JSON.stringify(event));
}
public function sayHello():String
{
return ec.call("sayHello") as String;
}
/**
* 转换MP3文件 ,需要传递一个路径过去
*
*/
public function wavToMP3(pcmPath:String):String{
return ec.call("wavToMP3",pcmPath) as String;
}
}
}
ANE开发步骤完整版 ANE for iOS