Open overfile opened 6 years ago
After a whole night of breaking my head I discovered that the Soundfingerprinting library gives exceptions with IL2CPP because
I have reproduce the error in android by changing the scripting backed to IL2CPP
08-04 19:02:05.945 7555 7570 E Unity : ExecutionEngineException: Attempting to call method 'System.Linq.Enumerable+WhereSelectEnumerableIterator2<System.Collections.Generic.KeyValuePair
2[[System.UInt64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], System.UInt64>::Select
The error jumps when attempting to check the recorded audio on the mic with the generated fingerprint.
Nice job. I can't promise I'll have time to help you out but I'll keep an eye on this thread. If you figure it out, a Pull Request is definitely welcome.
Thank you!!
Yes, if it seems right, I'll be putting what I'm finding here and as soon as we have the solution we make a commit (I'll need help, it's the first time I participate in a github project).
After an investigation by Internet I have limited the problem to this linq query:
return counter.Where(pair => pair.Value >= threshold).Select(p => p.Key);
The class is SubFingerprintGroupingCounter....
All code:
using System.Collections.Generic;
using UnityEngine;
namespace SoundFingerprinting.Utils
{
using System.Linq;
internal static class SubFingerprintGroupingCounter
{
public static unsafe IEnumerable<ulong> GroupByAndCount(List<ulong>[] subFingerprints, int threshold)
{
var counter = new Dictionary<ulong, int>();
for (int i = 0; i < subFingerprints.Length; ++i)
{
for (int j = 0; j < subFingerprints[i].Count; ++j)
{
ulong key = subFingerprints[i][j];
int count;
counter.TryGetValue(key, out count);
counter[key] = count + 1;
}
}
//Debug.Log("Localizado el problema aquí, en GroupByAndCount");
return counter.Where(pair => pair.Value >= threshold).Select(p => p.Key);
}
}
}
If we could replace this query with a few loops I think it would work correctly in IL2CPP...
I found a solution!
Finally the problem was due to the following instruction:
var subFingerprints = subFingeprintCount.Select(id => storage.ReadSubFingerprintById(id));
Found in the function: ReadSubFingerprints of the SubFingerprintDao class.
it seems that ahead of time (AOT) does not allow the call to an interface from a LINQ statement.
so in order to operate this class in IL2CPP it is necessary to manually perform the LINQ query.
I changed the function and I checked that with IL2CPP works correctly in both Android and IOS.
public IEnumerable<SubFingerprintData> ReadSubFingerprints(int[] hashes, int thresholdVotes, IEnumerable<string> assignedClusters)
{
var subFingeprintCount = CountSubFingerprintMatches(hashes, thresholdVotes);
//var subFingerprints = subFingeprintCount.Select(id => storage.ReadSubFingerprintById(id));
List<SubFingerprintData> N2 = new List<SubFingerprintData>();
foreach (var data in subFingeprintCount)
{
//N2 = storage.ReadSubFingerprintById(data);
N2.Add(storage.ReadSubFingerprintById(data));
}
var clusters = assignedClusters as List<string> ?? assignedClusters.ToList();
if (clusters.Any())
{
return N2.Where(subFingerprint => subFingerprint.Clusters.Intersect(clusters).Any());
}
return N2;
//return subFingerprints;
}
Good job, nice find. Can you make a pull request?
Hi!
I have managed to receive very positive results in queries when testing on windows, android and mac.
But now I'm testing it on an iPad and I can not get it to recognize any query.
Could it be a matter of codecs with the wav extensions or that the audio captured by the microphone is being bad?
I do not know where to go to make it work on ipad. I'm very surprised that the Mac works perfectly.
Any idea of where the solution might be?
PS: I have ruled out that the microphone does not work since in other applications I record the audio well but I can not assure that the quality of the microphone is good although on the other hand since a Chinese mobile android works well...