Страницы

Поиск по вопросам

четверг, 14 марта 2019 г.

Дозапись в существующий аудиофайл

У меня есть аудиофайл, который хранится на SD card, я хочу дозаписать аудио в конец этого файла, способы которые я нашла как это можно сделать - это использование SequenceInputStream или ffmpeg. Есть ли еще какие-то варианты как это можно сделать?


Ответ

Если это не закодированный, "сырой" аудиофайл wav, pcm, то дописать можно с помощью AudioRecord из android sdk.
Если закодированный, то чтобы дописать надо все раскодировать, дописать и снова закодировать. Если это делать на андройде, то можно воспользоваться MediaCodec api, зависит от кодека, надо смотреть какие поддерживает. Правда в сети мало примеров, и я в свое время не разобрался.
Другой вариант, более простой - ffmpeg. Здесь можно бинариник ффмпега засунуть в приложение и работать как из командной строки. Либо воспользоваться библиотекой javaCV. Хороший пример использования RecordActivity.java.
Кодирование/декодирование через ффмпег на андройде медленно работает, поэтому в свое время на проекте всякие такие медиа дела я делал через него же, но на сервере.

Передвижение элемента мышкой (crop image)

При перемещении курсора за пределы изображения, теряется событие mousedown
Как создать правильный обработчик? Как запретить crop выход за пределы изображения? Как добавить возможность изменения размера crop, при crop_image 256х160?
input = document.querySelector('.box input'); input.onchange = function() { image = new Image(); image.src = window.URL.createObjectURL(this.files[0]); this.parentNode.style = 'display: none'; document.querySelector('.box').innerHTML += "

" + image.outerHTML + "
" + "
" + image.outerHTML + "
"; crop = document.querySelector('.crop'); crop_image = document.querySelector('.crop_image img'); crop.onmousedown = function() { this.onmousemove = function(e) { this.style.marginTop = parseInt(this.style.marginTop) + e.movementY + 'px'; this.style.marginLeft = parseInt(this.style.marginLeft) + e.movementX + 'px'; crop_image.style.marginTop = '-' + this.style.marginTop; crop_image.style.marginLeft = '-' + this.style.marginLeft; return false; } this.onmouseup = function() { this.onmousemove = null; } } } .box { position: relative; width: 768px; height: 256px; background: #FFF; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .3); padding: 2px; } .select { position: absolute; width: 100%; cursor: pointer; line-height: 256px; text-align: center; font-family: Segoe UI; font-size: 20px; font-weight: 300; color: #C7254E; } .original_image img { max-height: 256px; } .original_image { position: relative; float: left; overflow: hidden; max-height: 256px; margin-right: 2px; } .crop { position: absolute; top: 0; width: 256px; height: 160px; box-shadow: 0 0 0 512px rgba(0, 0, 0, .4); cursor: move; } .crop_image img { max-height: 256px; } .crop_image { width: 256px; height: 160px; overflow: hidden; }


Ответ

Нужно следить за сдвигом кропа внутри блока с изображением и не выпускать его за рамки относительно ширины изображения.
input = document.querySelector('.box input'); input.onchange = function() { image = new Image(); image.src = window.URL.createObjectURL(this.files[0]); this.parentNode.style = 'display: none'; document.querySelector('.box').innerHTML += "

" + image.outerHTML + "
" + "
" + image.outerHTML + "
"; function getOffset(el) { var _x = 0; var _y = 0; while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) { _x += el.offsetLeft - el.scrollLeft; _y += el.offsetTop - el.scrollTop; el = el.offsetParent; } return { top: _y, left: _x }; } image.addEventListener("load", function() { var original = document.querySelector('.original_image'); var min_left = 0; var min_top = 0; var max_right = original.offsetWidth; var max_bottom = original.offsetHeight; crop = document.querySelector('.crop'); crop_image = document.querySelector('.crop_image img'); crop.onmousedown = function() { this.onmousemove = function(e) { var top = ((parseInt(this.style.marginTop) + e.movementY) < min_top) ? min_top : (parseInt(this.style.marginTop) + e.movementY); if (top + crop.offsetHeight > max_bottom) { top -= (top + crop.offsetHeight) - max_bottom; } this.style.marginTop = top + 'px'; var left = ((parseInt(this.style.marginLeft) + e.movementX) < min_left) ? min_left : (parseInt(this.style.marginLeft) + e.movementX); if (left + crop.offsetWidth > max_right) { left -= (left + crop.offsetWidth) - max_right; } this.style.marginLeft = left + 'px'; crop_image.style.marginTop = '-' + this.style.marginTop; crop_image.style.marginLeft = '-' + this.style.marginLeft; return false; } this.onmouseup = function() { this.onmousemove = null; this.onmouseleave = null; this.onmouseup = null; } this.onmouseleave = function() { this.onmousemove = null; this.onmouseleave = null; this.onmouseup = null; } } }); } .box { position: relative; width: 768px; height: 256px; background: #FFF; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .3); padding: 2px; } .select { position: absolute; width: 100%; cursor: pointer; line-height: 256px; text-align: center; font-family: Segoe UI; font-size: 20px; font-weight: 300; color: #C7254E; } .original_image img { max-height: 256px; } .original_image { position: relative; float: left; overflow: hidden; max-height: 256px; margin-right: 2px; } .crop { position: absolute; top: 0; width: 256px; height: 160px; box-shadow: 0 0 0 512px rgba(0, 0, 0, .4); cursor: move; } .crop_image img { max-height: 256px; } .crop_image { width: 256px; height: 160px; overflow: hidden; }

Скрытый тулбар и ошибки binding

У меня есть следующий xaml:

and two classes as possible data context - for two different windows.
class ToolbarContextOne { public Visibility SomeProperty {get;set;} } class ToolbarContextTwo:ToolbarContextOne { public bool IsEnabled {get;set;} }
Я использую тулбар из примера в нескольких ситуациях. Для того, чтобы показывать различные данные в разных окнах, я использую разные дата контексты. Когда мне не нужна вышеупомянутая секция, я просто ставлю SomeProperty в Visibility.Collapsed. Но всё равно получаю binding error для свойства IsEnabled. Очевидно, парсер пытается выполнить все binding expressions. Есть способ заставить его не выполнять эти выражения в скрытой секции xaml?


Ответ

Наверное, более чистый путь через DataTemplate
Положите где-нибудь в ресурсы (например, глобальные, или локально в окно, или в UserControl) такое:


Ну и в том месте, где у вас был ToolbarTray, просто

При этом ContentPresenter найдёт нужный DataTemplate и использует его.

Ошибка синтаксиса при вставке данных в БД

Никак не пойму где я ошибаюсь. You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''persons' VALUES ('123', dfgh, kkk, 33)' at line 1
$result = mysql_query("INSERT INTO 'persons' VALUES ($idInput, $nameInput, $lnameInput, $ageInput)" , $db) or die(mysql_error());


Ответ

кавычки вокруг строковых значений кто будет проставлять? и поставьте MySQL Workbench, он автоматически подсвечивает строку с некорректным синтаксисом, в нем и дебажьте ваши запросы
p.s. и у вас еще одна ошибка (первопричина, кстати) - одинарные кавычки вокруг имени таблицы
mysql> use 'db'; #здесь корректно, но излишне, это внутренняя команда mysql # хотя use db тоже сработает (и быстрее печатать) Database changed mysql> show tables; +--------------+ | Tables_in_db | +--------------+ | OrderHistory | | users | +--------------+ 2 rows in set (0.00 sec) #здесь некорректно, не по стандарту SQL mysql> select * from 'users'; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''users'' at line 1
во первых, в этом запросе кавычки вокруг имени таблицы не нужны, а во вторых, правильные кавычки для sql - это backticks:
mysql> select * from `users`; +----+------------+- | id | login
ответ к комменту касательно кавычек вокруг полей типа INT/DOUBLE/FLOAT и т.д.: они возможны, но не обязательны. При малой нагрузке лишний байтик потраченный на передачу кавычек незаметен.
При большой нагрузке, при вставке больших объемов данных (когда вы вставляете данные вплоть до max_allowed_packet) , когда у вас идет множество числовых полей, вы получите дополнительную нагрузку/придется снизить количество рядов, которые вы можете вставить одновременнно.
Кроме того, чисто семантически это дает понять, когда вы просматриваете какой-нибудь большой запрос, что цифры должны вставляться в колонку с числовым типом.
Когда вы видите такой запрос, вы понимаете, что в этом есть логика и намерение.

Как работает java.util.concurrent.Phaser?

Как, в данном задании, Phaser понимает, что нити являются его участниками?
Вызвав метод arriveAndAwaitAdvance(), он присоединяет нить, в которой вызван, к пасеру в состоянии прибыла на барьер?
Phaser понимает, что нити являются его участниками, за счет методов arriveAndAwaitAdvance и arrive?
Без их вызова в данной задаче он будет пустой?
package com.javarush.test.level28.lesson10.home01;
import java.util.ArrayList; import java.util.List; import java.util.concurrent.Phaser;
public class Solution { public static void main(String[] args) throws InterruptedException { List characters = new ArrayList<>(); characters.add(new Plant()); characters.add(new Plant()); characters.add(new Zombie()); characters.add(new Zombie()); characters.add(new Zombie()); start(characters); }
private static boolean isEveryoneReady = false;
private static void start(List characters) throws InterruptedException { final Phaser phaser = new Phaser(1 + characters.size());
for (final Character character : characters) { final String member = character.toString(); System.out.println(member + " присоединился к игре");
new Thread() { @Override public void run() { System.out.println(member + " готовится играть"); phaser.arriveAndAwaitAdvance(); if (!isEveryoneReady) { isEveryoneReady = true; System.out.println("Игра началась!"); } character.run(); } }.start();
}
phaser.arriveAndDeregister(); } }


Ответ

Phaser -- это разновидность барьера, аналогичен CyclicBarrier и CountDownLatch, но отличается более гибкой настройкой.
Барьер в общем виде представляет собой следующее:
задается количество потоков, которое должно собраться на барьере каждый поток, прибывающий на барьер, блокируется как только на барьере собирается заданное выше количество потоков, барьер "открывается", и все потоки продолжают свою работу
Подробнее почитать про барьеры (в т.ч. про эти три реализации) и посмотреть иллюстрацию их работы можно в статье на Хабре
В приведенном коде Phaser работает так:
инициализируется значением участников 1 + characters.size() дальше потоки в количестве characters.size() регистрируются в нем и блокируются при вызове метода arriveAndDeregister() происходит регистрация последнего участника, барьер "открывается", все потоки продолжают свою работу. При этом этот метод автоматически уменьшает количество зарегистрированных участников для следующего этапа, но в данном коде это не имеет значения.

Отвечая на конкретные вопросы:
Вызвав метод arriveAndAwaitAdvance(), он присоединяет нить, в которой вызван, к пасеру в состоянии прибыла на барьер?
Да.
Phaser понимает, что нити являются его участниками, за счет методов arriveAndAwaitAdvance и arrive?
Да.
Без их вызова в данной задаче он будет пустой?
Не совсем понятно, что вы имеете в виду. Он будет "пустой" в том смысле, что счетчик зарегистрированных участников в нем будет равен нулю.

P.S. Кстати у вас есть проблема с полем isEveryoneReady -- доступ к нему не синхронизирован и вы можете получить несколько сообщений "Игра началась!".

JS - не работает append()

Не добавляет в textarea смайлы (точнее их текстовые обозначения), в чем проблема?
В js не силен, а методом научного тыка получается или смайлы отправить, но текст не отправляется, или наоборот.
В шапке подключен jquery-1.7.1.js

  • ------------------- еще 18 смайлов ----------------


  • Ответ

    onClick="javascript: $('.textarea').val($('.textarea').val()+'::1::')"
    посмотреть, как работает

    Поиск вхождения целочисленного массива, Си

    Добрый день. Пусть имеется два массива целых чисел:
    int arr1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr2[] = {3, 4, 5};
    Существует ли функция (наподобие strstr для строк), которая вернет указатель, если arr2 входит в arr1, и вернет NULL, если вхождение не найдено.


    Ответ

    Набросал вариант в лоб:
    #include #include
    int find_subarray(const int *a, size_t an, const int *b, size_t bn) { for (int i = 0; i <= an - bn; i++) { if (memcmp(a + i, b, bn * sizeof(int)) == 0) return i; }
    return -1; }
    int main() { int a[] = {2, 5, 1}; int b[] = {2, 5, 1}; int pos = find_subarray(a, sizeof(a)/sizeof(int), b, sizeof(b)/sizeof(int));
    if (pos >= 0) printf("B = A[%i, %lu]
    ", pos, pos + sizeof(b)/sizeof(int)); else printf("B is not subarray of A
    ");
    return 0; }

    Почему при сортировке данных получаются числа в другом формате?

    Имеются данные которые нужно подготовить к объединению с другим блоком данных. Для этого хотелось бы хронологично упорядочить их. Пример исходных данных:
    df1
    pid syear pgsbil pgfamstd \ 0 101 1984 [3] Fachhochschulreife [1] verheiratet zus. 1 101 1985 [3] Fachhochschulreife [1] verheiratet zus. 2 101 1986 [3] Fachhochschulreife [1] verheiratet zus. ... ... ... ... 6 102 1984 [1] Hauptschulabschluss [1] verheiratet zus. 7 102 1985 [1] Hauptschulabschluss [1] verheiratet zus. ... ... ... ... 484168 31433802 2012 [2] Realschulabschluss [1] verheiratet zus. 484169 31433901 2012 [4] Abitur [2] verheiratet getr.
    Я пробовал отсортировать используя код:
    DF1 = df1.sort_values(by='syear', ascending=1)
    Но вместо года я получаю, по моему мнению, его в другой кодировке (как и всё остальное!):
    Df1 Out[53]: pid syear pgsbil pgfamstd \ 248899 320797655 -32656 81 -95 248825 891723238 -32419 43 43 250014 345587954 -32377 NaN -119 ... ... ... ... 250163 957561202 31108 -91 27 250166 449665857 31554 -1 -1
    Почему при сортировке данных получаются числа в другом формате? Как мне исправить это?


    Ответ

    похоже у вас в колонке syear или действительно отрицательные числа или, что скорее всего, большие положительные (больше 32767), которые при типе данных np.int16 превращаются в отрицательные...
    Демо:
    информация о max() и min() для типа np.int16
    In [67]: np.iinfo(np.int16) Out[67]: iinfo(min=-32768, max=32767, dtype=int16)
    как из большого положительного целого (32880) получется отрицательное (-32656) при использовании типа np.int16
    In [72]: df = pd.DataFrame({'a':[32880]}, dtype=np.int16)
    In [73]: df Out[73]: a 0 -32656
    неправильные ("плохие") года:
    In [88]: df1.query('syear <= 1980 or syear > 2016').syear Out[88]: 248737 -9076 248738 -26593 248739 1725 248740 -25171 248741 7963 248742 27137 248743 19854 248744 26738 248745 6716 248746 9885 248747 19361 248748 -19726 248749 -24605 248750 24074 248751 -8070 248752 -16027 248753 -23424 248754 3848 248755 1471 248756 30634 248757 -8162 248758 -18937 248759 16733 248760 -21923 248761 16817 248762 3834 248763 -13556 248764 -16229 248765 24272 248766 25642 ... 252510 -1 252511 -1 252512 -1 252513 -1 252514 -1 252515 -1 252516 -1 252517 -1 Name: syear, dtype: int16
    Интересное наблюдение - все "плохие" данные идут непрерывным блоком (с индексами: 248737 - 252517)

    TCP мониторинг подключения приложения

    Делаю консольное приложение, которое должно проверять подключение к определенному IP и выполнять определенные действия. Как мониторить такое подключение? Тут выводится список всех исходящих, как отфильтровать и оставить только одно?
    static void ListAvailableTCPPort(ref ArrayList usedPort) { IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections(); IEnumerator myEnum = tcpConnInfoArray.GetEnumerator();
    while (myEnum.MoveNext()) { TcpConnectionInformation TCPInfo = (TcpConnectionInformation)myEnum.Current; Console.WriteLine("{0}", TCPInfo.RemoteEndPoint); usedPort.Add(TCPInfo.LocalEndPoint.Port); } }
    public static void Main() { ArrayList usedPorts = new ArrayList(); ListAvailableTCPPort(ref usedPorts); Console.ReadKey(); }


    Ответ

    Если вам необходимо проверять подключение к определенному IP-адресу,то вы должны фильтровать 1. поле RemoteEndPoint - указывает на IP-адрес и порт TCP-соединения, который вас интересует 2. У подключения должно быть состояние(State)- Established, которое означает что соединение установлено и данные могут быть отправлены.
    Вот пример кода:
    static void SearchAvailableTCPConnection(ref ArrayList usedPort, string searchAddress, int searchPort) { IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint filterEndpoint = new IPEndPoint(IPAddress.Parse(searchAddress), searchPort);
    TcpConnectionInformation tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections().Where(g => g.RemoteEndPoint.Equals(filterEndpoint) && g.State ==TcpState.Established).FirstOrDefault(); if (tcpConnInfoArray != null) { Console.WriteLine("Port {0} {1} {2} ", tcpConnInfoArray.LocalEndPoint, tcpConnInfoArray.RemoteEndPoint, tcpConnInfoArray.State); } }
    private static void Main(string[] args) { ArrayList usedPorts = new ArrayList(); SearchAvailableTCPConnection(ref usedPorts, "192.168.0.2", 8090); Console.ReadKey(); }
    На экран будет выведено сообщение только в том случае, если у нас есть активное TCP-соединение с IP-адресом 192.168.0.2 по порту 8090.
    Для конвертации строки IP-адреса в класс IPAddress, используем статическую функцию этого класса Parser