原來可以識別給定PCM陣列GNSDK爲Android以下三個GnMusicIdStream API調用:
- GnMusicIdStream.audioProcessStart(sampleRateHz,pcmBitcount,信道計數)準備識別引擎的進入PCM
- GnMusicIdStream.audioProcess(pcmArray,pcmArray.length)到要認識到
- GnMusicIdStream.identifyAlbumAsync()來生成指紋,然後用它來查找操作PCM陣列中傳遞。這將導致傳遞給GnMusicIdStream實例的IGnMusicIdStreamEvents對象的回調,並且musicIdStreamAlbumResult()將提供任何結果。
就我所見,使用這種方法你不需要等待指紋的生成等顯式 - 你只需要按順序調用這三個方法,然後GNSDK處理剩下的,最終將發出一個回電話。完整ID操作結束這樣看:
try {
mGnMusicIdStream = new GnMusicIdStream(mGnUser, GnMusicIdStreamPreset.kPresetRadio, new IGnMusicIdStreamEvents() {
@Override
public void musicIdStreamProcessingStatusEvent(GnMusicIdStreamProcessingStatus gnMusicIdStreamProcessingStatus, IGnCancellable iGnCancellable) {
Log.d(TAG,"gracenote gnsdk -- musicIdStreamProcessingStatusEvent(); event is: "+gnMusicIdStreamProcessingStatus);
}
@Override
public void musicIdStreamIdentifyingStatusEvent(GnMusicIdStreamIdentifyingStatus gnMusicIdStreamIdentifyingStatus, IGnCancellable iGnCancellable) {
Log.d(TAG,"gracenote gnsdk -- musicIdStreamIdentifyingStatusEvent(); event is: "+gnMusicIdStreamIdentifyingStatus);
}
@Override
public void musicIdStreamAlbumResult(GnResponseAlbums gnResponseAlbums, IGnCancellable iGnCancellable) {
Log.d(TAG,"gracenote gnsdk -- musicIdStreamAlbumResult(); responsealbums matches: "+gnResponseAlbums.resultCount());
if (gnResponseAlbums.resultCount() > 0) {
try {
final GnAlbum albumResponse = gnResponseAlbums.albums().at(0).next();
final GnTrack trackResponse = albumResponse.trackMatched();
if (trackResponse != null) {
mEvent.postOnGNSearchResult(new ISongRecognitionResponse() {
@Override
public
@NonNull
String extractTrackTitle() {
// seems that track title comes reliably from GnTrack and much of the rest is locked
// up in the GnAlbum?
if (trackResponse.title() != null) {
return trackResponse.title().display();
} else {
return "";
}
}
@Override
public
@NonNull
String extractTrackArtist() {
if (albumResponse.artist() != null) {
if(BuildConfig.RULE_DEBUG_LEVEL>0)
Log.d(TAG,"gnsdk -- album artist says "+albumResponse.artist().name().display());
return albumResponse.artist().name().display();
} else {
return "";
}
}
@Override
public long extractTrackPosition() {
return trackResponse.currentPosition();
}
@Override
public long extractTrackDuration() {
return trackResponse.duration();
}
@Override
public byte[] extractCoverArtImageData() {
// seems that base64 string of the image is not always/commonly available
// at least as we're trying to access it here. The sample app downloads the image
// asynchronously from the URL, which seems more reliable
String img64 = albumResponse.coverArt().asset(GnImageSize.kImageSizeSmall).imageDataBase64(); //trackResponse.content(GnContentType.kContentTypeImageCover).asset(GnImageSize.kImageSize220).imageDataBase64();
if(img64 != null && !img64.isEmpty()) {
return Base64.decode(img64, Base64.DEFAULT);
}else{
return null;
}
}
@NonNull
@Override
public String extractCoverArtImageURL() {
// beware: asking for specific image sizes has been known to cause
// no cover art to come back even if there might be cover art at another size.
// The sample app uses the categorical size qualifier constant kImageSizeSmall
String httpURL = albumResponse.coverArt().asset(GnImageSize.kImageSizeSmall).urlHttp();
return httpURL;
}
});
}//end if track response data is non-null
else {
mEvent.postOnGNSearchResult(null);
}
}catch(GnException e){
Log.e(TAG, "we received a response clbk, but failed to process it", e);
}
}//end if greater than 0 results
else{
//no results, so pass a null result to indicate a miss
mEvent.postOnGNSearchResult(null);
}
}
@Override
public void musicIdStreamIdentifyCompletedWithError(GnError gnError) {
Log.e(TAG,"gnsdk -- musicIdStreamIdentifyCompletedWithError(); we received a response clbk, but failed to process it");
mEvent.postOnGNSearchFailure(gnError.errorDescription());
}
@Override
public void statusEvent(GnStatus gnStatus, long l, long l1, long l2, IGnCancellable iGnCancellable) {
Log.e(TAG,"gnsdk -- statusEvent(); status is: "+gnStatus);
}
});
//configure the options on the gnmusicidstream instance
mGnMusicIdStream.options().lookupData(GnLookupData.kLookupDataContent, true);
mGnMusicIdStream.options().lookupData(GnLookupData.kLookupDataSonicData, true);
mGnMusicIdStream.options().lookupMode(GnLookupMode.kLookupModeOnline);
mGnMusicIdStream.options().preferResultCoverart(true);
mGnMusicIdStream.options().resultSingle(true);
//configure audio processing params on gnmusicidstream
mGnMusicIdStream.audioProcessStart(sampleRateHz,pcmBitcount,channelCount);
//pass the pcm array to the gnmusicidstream for processing
mGnMusicIdStream.audioProcess(pcmArray,pcmArray.length);
//initiate the lookup operation based on the processed pcm
mGnMusicIdStream.identifyAlbumAsync();
}catch(GnException e){
Log.e(TAG,"gnsdk -- failed recognition operation",e);
}
返回數據是怎麼樣的混亂,與提取有關查詢的某些方面,而不是當在查詢時可以爲空或空軌道的元數據的多個潛在途徑其他方法。到目前爲止,我發現關於GnResponseAlbums響應對象有趣的觀點(我不知道下文提到的返回值的空性合同,所以,要當心NullPointerException異常):
gnResponseAlbums.resultCount()將如果沒有明確出錯,則爲0,但沒有找到匹配。
匹配的GnTrack可以通過albumResponse檢索。trackMatched()
音軌標題可以檢索與albumResponse.trackMatched()的字符串。標題()。顯示()
軌道藝術家可以與albumResponse.artist()進行檢索。名().display()
當前曲目的時間位置可以通過albumResponse.trackMatched()。currentPosition()來提取,這在確定歌曲結束的時間似乎非常精確{endTime = currentTime +持續時間 - currentPosition}
trackResponse.trackMatched()。duration()
封面藝術URL可以通過albumResponse.coverArt()。asset(GnImageSize.kImageSizeSmall).urlHttp()來提取。
我沒有任何運氣得到通過albumResponse.coverArt()捆綁爲一個base64字符串的圖像。資產(GnImageSize.kImageSizeSmall).imageDataBase64(),但GNSDK提供了一個簡單GnAssetFetch類可用於下拉封面數據如下
GnAssetFetch assetData = new GnAssetFetch(mGnUser,coverArtUrl);
byte[] data = assetData.data();
作爲用於消除在正在進行的操作中,可以使用的GnMusicIdStream實例的identifyCancel()方法。如果取消將發生在IGnMusicIdStreamEvents回調方法中,則應該使用提供的IGnCancellable消除器。