我正在努力将我的Android应用程序从旧版Gracenote移动客户端迁移到更新的GNSDK for Mobile SDK,我遇到了一些障碍:
答案 0 :(得分:0)
事实证明,您可以使用以下三个GnMusicIdStream API调用识别GNSDK for Android中的给定PCM阵列:
据我所知,使用这种方法你不需要明确地等待指纹生成等 - 你只需按顺序调用这三种方法然后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响应对象的有趣观点(我不确定下面提到的返回值的可空性合同,所以要注意nullpointerexceptions):
gnResponseAlbums.resultCount()如果没有明确错误但是没有找到匹配项,则为0。
可以使用albumResponse.trackMatched()
可以使用albumResponse.trackMatched()。title()。display()
可以使用albumResponse.artist()检索曲目艺术家.name()。display()
可以使用albumResponse.trackMatched()。currentPosition()提取当前曲目时间位置,这在确定歌曲结束的时间时似乎非常准确{endTime = currentTime + duration - currentPosition}
可以使用albumResponse.trackMatched()提取曲目的持续时间。duration()
可以使用albumResponse.coverArt()。asset(GnImageSize.kImageSizeSmall).urlHttp()提取封面艺术网址。
我没有幸运通过albumResponse.coverArt()。asset(GnImageSize.kImageSizeSmall).imageDataBase64()将图像捆绑为base64字符串,但GNSDK提供了一个简单的GnAssetFetch类,可以使用它下载封面艺术数据如下
GnAssetFetch assetData = new GnAssetFetch(mGnUser,coverArtUrl);
byte[] data = assetData.data();
对于取消正在进行的操作,可以使用GnMusicIdStream实例的identifyCancel()方法。如果取消将在IGnMusicIdStreamEvents回调方法中发生,则应使用提供的IGnCancellable取消器。