Мысль [приблизительно 114] @dp AnonCast и решенный для испытания его немного. Вот то, что я придумываю, который мог бы быть полезен для некоторых:
// using the concepts of dp's AnonCast
static Func<T> TypeCurry<T>(Func<object> f, T type)
{
return () => (T)f();
}
И вот то, как это могло бы использоваться:
static void Main(string[] args)
{
var getRandomObjectX = TypeCurry(GetRandomObject,
new { Name = default(string), Badges = default(int) });
do {
var obj = getRandomObjectX();
Console.WriteLine("Name : {0} Badges : {1}",
obj.Name,
obj.Badges);
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
static Random r = new Random();
static object GetRandomObject()
{
return new {
Name = Guid.NewGuid().ToString().Substring(0, 4),
Badges = r.Next(0, 100)
};
}
Хорошо, у меня есть несколько ответов после еще нескольких тестов, поэтому я делюсь ими с любыми заинтересованными.
Я поместил переменную для измерения временных интервалов между тиками в методе play
(метод, который фактически отправляет сообщение play
объекту AVAudioPlayer
), и как мое простое сравнение с внешним эксперимент показал, что 60 ударов в минуту были слишком медленными - я получил эти временные интервалы (в секундах):
1.004915
1.009982
1.010014
1.010013
1.010028
1.010105
1.010095
1.010105
Мой вывод состоял в том, что некоторые служебные данные истекают после подсчета каждого интервала в 1 секунду, и это дополнительное время (около 10 мсек) накапливается до заметной величины через несколько десятков секунд - что очень плохо для метронома. Поэтому вместо того, чтобы измерять интервал между вызовами, я решил измерить общий интервал с первого вызова, чтобы ошибка не накапливалась. Другими словами, я заменил это условие:
while (continuePlaying && ((currentTime0 + [duration doubleValue]) >= currentTime1)
на это условие:
while (continuePlaying && ((_currentTime0 + _cnt * [duration doubleValue]) >= currentTime1 ))
, где теперь _currentTime0
и _cnt
являются членами класса (извините, если это c ++ Жаргон, я новичок в Obj-C), первый содержит метку времени первого вызова метода, а последний - int
счетное число тиков (== вызовов функций). Это привело к следующим измеренным временным интервалам:
1.003942
0.999754
0.999959
1.000213
0.999974
0.999451
1.000581
0.999470
1.000370
0.999723
1.000244
1.000222
0.999869
, и даже без вычисления среднего значения очевидно, что эти значения колеблются около 1,0 секунды (а среднее значение близко к 1,0 с точностью, по крайней мере, в миллисекундах) ).
Я буду рад услышать больше информации о том, что вызывает дополнительное время - 10 мсек звучит как вечность для современного процессора - хотя я не знаком со спецификациями процессора iPod (это iPod 4G, и Википедия говорит, что CUP - это PowerVR SGX GPU 535 при 200 МГц)
Использование цикла while и режима сна для измерения времени метронома не является надежным способом решения этой проблемы, поскольку, как вы видели, он может вызывать колебания и смещения. Я считаю, что стандартным способом решения этой проблемы является использование Core Audio (так или иначе) для подачи непрерывного аудиопотока, содержащего тики метронома, разделенные правильной величиной молчания между ними, в зависимости от темпа. Поскольку вы знаете точную частоту дискретизации, вы можете очень точно рассчитать время тиков. К сожалению, создать аудио самостоятельно немного сложнее, чем то, что вы пытаетесь сделать, но этот вопрос Stackoverflow может помочь вам начать.