2012-05-27 9 views
32

मैं ओपनएसएल ईएस फाइलडिस्क्रिप्टर ऑब्जेक्ट का उपयोग करके एक ऑडियो एसेट से एक बाइट बफर प्राप्त करना चाहता हूं, इसलिए मैं फ़ाइल को चलाने/बंद/ढूंढने के लिए एसएल इंटरफेस का उपयोग करने के बजाय इसे सरलबफरक्यूयू में बार-बार एनक्यू्यू कर सकता हूं।क्या ओपनएसएल ईएस (एंड्रॉइड के लिए) में ऑडियो एसेट से सीधे बाइट बफर प्राप्त करना संभव है?

वहाँ तीन मुख्य कारणों क्यों मैं सीधे नमूना बाइट्स प्रबंधित करना चाहते हैं कर रहे हैं:

  1. OpenSL प्लेयर वस्तुओं के लिए/बंद/आदि खेलने के लिए एक audiotrack परत का उपयोग करता है। यह न केवल अवांछित ओवरहेड पेश करता है, बल्कि इसमें कई कीड़े भी हैं, और खिलाड़ी की तेज़ी से शुरू/बंद होने से कई समस्याएं होती हैं।
  2. मुझे सीधे कस्टम डीएसपी प्रभावों के लिए बाइट बफर में हेरफेर करने की आवश्यकता है।
  3. जिन क्लिप्सों को मैं खेलना चाहता हूं वे छोटे हैं, और फ़ाइल I/O ओवरहेड से बचने के लिए सभी को स्मृति में लोड किया जा सकता है। इसके अलावा, मेरे अपने बफर को एनक्यूइंग करने से मुझे आउटपुट सिंक में 0 लिखकर विलंबता कम हो जाएगी, और स्टॉपिंग, पोजिंग और ऑडियोट्रैक चलाने के बजाए, जब वे खेल रहे हों तो नमूना बाइट्स पर स्विच कर सकते हैं।

ठीक है, तो पूरा औचित्य - यहाँ है कि मैं क्या कोशिश की है - मैं एक नमूना struct जो होता है, अनिवार्य रूप से, एक इनपुट और आउटपुट ट्रैक, और एक बाइट सरणी नमूने धारण करने के लिए है। इनपुट मेरा फ़ाइलडिस्क्रिप्टर प्लेयर है, और आउटपुट एक SimpleBufferQueue ऑब्जेक्ट है। यहाँ मेरी struct है: एक फ़ाइल खिलाड़ी आरंभ fdPlayerObject के बाद

typedef struct Sample_ { 
    // buffer to hold all samples 
    short *buffer;  
    int totalSamples; 

    SLObjectItf fdPlayerObject; 
    // file descriptor player interfaces 
    SLPlayItf fdPlayerPlay; 
    SLSeekItf fdPlayerSeek; 
    SLMuteSoloItf fdPlayerMuteSolo; 
    SLVolumeItf fdPlayerVolume; 
    SLAndroidSimpleBufferQueueItf fdBufferQueue; 

    SLObjectItf outputPlayerObject; 
    SLPlayItf outputPlayerPlay; 
    // output buffer interfaces 
    SLAndroidSimpleBufferQueueItf outputBufferQueue;   
} Sample; 

, और malloc-इंग

sample->buffer = malloc(sizeof(short)*sample->totalSamples); 

मैं

// get the buffer queue interface 
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue)); 
के साथ अपने BufferQueue इंटरफेस हो रही है के साथ मेरी बाइट बफर के लिए स्मृति

फिर मैं आउटपुट प्लेयर:

को तुरंत चालू करता हूं
// create audio player for output buffer queue 
const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 
const SLboolean req1[] = {SL_BOOLEAN_TRUE}; 
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(sample->outputPlayerObject), &outputAudioSrc, &audioSnk, 
               1, ids1, req1); 

// realize the output player 
result = (*(sample->outputPlayerObject))->Realize(sample->outputPlayerObject, SL_BOOLEAN_FALSE); 
assert(result == SL_RESULT_SUCCESS); 

// get the play interface 
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_PLAY, &(sample->outputPlayerPlay)); 
assert(result == SL_RESULT_SUCCESS); 

// get the buffer queue interface for output 
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 
                &(sample->outputBufferQueue)); 
assert(result == SL_RESULT_SUCCESS);  

    // set the player's state to playing 
result = (*(sample->outputPlayerPlay))->SetPlayState(sample->outputPlayerPlay, SL_PLAYSTATE_PLAYING); 
assert(result == SL_RESULT_SUCCESS); 

मैं नमूना खेलने के लिए चाहते हैं, तो मैं उपयोग कर रहा हूँ:

Sample *sample = &samples[sampleNum]; 
// THIS WORKS FOR SIMPLY PLAYING THE SAMPLE, BUT I WANT THE BUFFER DIRECTLY 
// if (sample->fdPlayerPlay != NULL) { 
//  // set the player's state to playing 
//  (*(sample->fdPlayerPlay))->SetPlayState(sample->fdPlayerPlay, SL_PLAYSTATE_PLAYING); 
// } 

// fill buffer with the samples from the file descriptor 
(*(sample->fdBufferQueue))->Enqueue(sample->fdBufferQueue, sample->buffer,sample->totalSamples*sizeof(short)); 
// write the buffer to the outputBufferQueue, which is already playing 
(*(sample->outputBufferQueue))->Enqueue(sample->outputBufferQueue, sample->buffer, sample->totalSamples*sizeof(short)); 

बहरहाल, यह फ्रीज और बंद करने के लिए मेरे एप्लिकेशन का कारण बनता है। यहाँ कुछ गलत है। भी, मैं प्रत्येक बार फाइल डिस्क्रिप्टर के बफरक्यूयू से नमूने नहीं लेना पसंद करूंगा। इसके बजाए, मैं इसे बाइट सरणी में स्थायी रूप से संग्रहीत करना चाहता हूं, और जब भी मुझे पसंद हो तो उत्पादन को एनक्यू करें।

+2

हैलो खिनर, क्या यह आपको जावा बाइट या शॉर्ट सरणी में संपत्ति फ़ोल्डर से .wav- फ़ाइलों को पढ़ने में मदद करेगा और फिर इसे आगे संसाधित करेगा? –

+0

यह सुनिश्चित नहीं है कि मैं कितनी मदद कर सकता हूं, लेकिन सिर्फ रिकॉर्ड के लिए - क्या आप एनडीके का उपयोग कर रहे हैं? क्या आपका कोड सी ++ में क्यों है? – Erhannis

+2

हां, मैं एनडीके का उपयोग कर रहा हूं, और यह वास्तव में शुद्ध सी है। यह सवाल दांत में लंबा हो रहा है। मैंने इस पर बहुत प्रगति की है और एक सभ्य उत्तर जोड़ने के लिए चारों ओर मिल जाएगा। – khiner

उत्तर

5

पीसीएम को डीकोडिंग एपीआई स्तर 14 और उच्चतम पर उपलब्ध है।

जब आप डिकोडर खिलाड़ी बनाने आप एंड्रॉयड सरल बफर कतार सेट की जरूरत के रूप में डेटा सिंक:

// For init use something like this: 
SLDataLocator_AndroidFD locatorIn = {SL_DATALOCATOR_ANDROIDFD, decriptor, start, length}; 
SLDataFormat_MIME dataFormat = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; 
SLDataSource audioSrc = {&locatorIn, &dataFormat}; 

SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; 
SLDataSink audioSnk = { &loc_bq, NULL }; 

const SLInterfaceID ids[2] = {SL_IID_PLAY, SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 

SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(sample->fdPlayerObject), &outputAudioSrc, &audioSnk, 2, ids1, req1); 

विकोडक कतार के लिए आप एंड्रॉयड सरल बफर कतार है, जो भरा जाएगा करने के लिए खाली बफ़र्स का एक सेट enqueue की जरूरत पीसीएम डेटा के साथ।

इसके अलावा आपको डिकोडर कतार के साथ एक कॉलबैक हैंडलर पंजीकृत करने की आवश्यकता है जिसे पीसीएम डेटा तैयार होने पर बुलाया जाएगा। कॉलबैक हैंडलर को पीसीएम डेटा को संसाधित करना चाहिए, अब खाली बफर को फिर से लगाएं, और फिर वापस आएं।डीकोडेड बफर का ट्रैक रखने के लिए आवेदन ज़िम्मेदार है; कॉलबैक पैरामीटर सूची में पर्याप्त जानकारी शामिल नहीं है यह इंगित करने के लिए कि कौन सा बफर भर गया था या कौन सा बफर अगले को लागू करने के लिए है।

पीसीएम को डीकोड रोकें और प्रारंभिक तलाश का समर्थन करता है। वॉल्यूम नियंत्रण, प्रभाव, लूपिंग, और प्लेबैक दर समर्थित नहीं हैं।

अधिक जानकारी के लिए OpenSL ES for Android से पीसीएम पर ऑडियो डीकोड करें।

संबंधित मुद्दे