spassvogel / UnitySoundFingerprint

0 stars 0 forks source link

IL2CPP error #2

Open overfile opened 6 years ago

overfile commented 6 years ago

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...

overfile commented 6 years ago

After a whole night of breaking my head I discovered that the Soundfingerprinting library gives exceptions with IL2CPP because 'for which no ahead of time (AOT) code was generated.

overfile commented 6 years ago

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.KeyValuePair2[[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' for which no ahead of time (AOT) code was generated. 08-04 19:02:05.945 7555 7570 E Unity : 08-04 19:02:05.945 7555 7570 E Unity : Rethrow as AggregateException: One or more errors occurred. 08-04 19:02:05.945 7555 7570 E Unity : at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00000] in <00000000000000000000000000000000>:0 08-04 19:02:05.945 7555 7570 E Unity : Rethrow as AggregateException: One or more errors occurred. 08-04 19:02:05.945 7555 7570 E Unity : at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00000] in <00000000000000000000000000000000>:0 08-04 19:02:05.945 7555 7570 E Unity : 08-04 19:02:05.945 7555 7570 E Unity : (Filename: currently not available on il2cpp Line: -1) 08-04 19:02:05.945 7555 7570 E Unity :

The error jumps when attempting to check the recorded audio on the mic with the generated fingerprint.

spassvogel commented 6 years ago

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.

overfile commented 6 years ago

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...

overfile commented 6 years ago

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;
        }
spassvogel commented 6 years ago

Good job, nice find. Can you make a pull request?