Bitperfekt Toslink loopback i Linux

Hemmapulare debatterar lämpligen i detta forum.

Moderator: Redaktörer

Användarvisningsbild
pLudio
 
Inlägg: 2753
Blev medlem: 2003-06-17
Ort: Stockholm

Bitperfekt Toslink loopback i Linux

Inläggav pLudio » 2024-09-15 19:17

Efter en del pulande har jag lyckats verifiera bittrogen återgivning i Linux över Toslink. För att minska på lagren av komplexitet så har jag valt att gå direkt på ALSA istället för via PulseAudio eller PipeWire som man annars bör använda idag.

Jag köpte en, i mitt tycke egentligen för dyr, Hifime S2 Digi (Savitech SA9227 chip) men vill man inte köpa ett helt USB-ljudkort med Toslink in så finns det inte så många alternativ som klarar av 192 kHz och är USB Audio Class 2 (man slipper installera drivrutin i moderna OS).

Jag stängde av SA9227 USB-ljudkortet med pwvucontrol för PipeWire.
PipeWire_SA9227_Off.png
PipeWire_SA9227_Off.png (24 KiB) Visad 1837 gånger

Och SA9227 syns inte längre bland ljudenheterna i PipeWire:
Kod: Markera allt
$ pw-cli list-objects | grep device.name


Man kan även stänga av SA9227 permanent i WirePlumber för PipeWire. ~/.config/wireplumber/wireplumber.conf.d/hifime_s2_digi.conf:
Kod: Markera allt
monitor.alsa.rules = [
  {
    matches = [
      {
        # This matches the value of the 'device.name' property of the device.
        device.name = "~alsa_card.usb-HiFimeDIY_SA9227_USB_Audio.*"
      }
    ]
    actions = {
      update-props = {
        # Apply all the desired device settings here.
        device.disabled = true
      }
    }
  }
]

Starta om WirePumber med: systemctl --user restart wireplumber.service

I ALSA förekommer en massa ljudenheter för SA9227 och de intressanta är:
Kod: Markera allt
$ aplay -L | grep -A 1 -B 1 SA9227
hw:CARD=Audio,DEV=0
    SA9227 USB Audio, USB Audio
    Direct hardware device without any conversions
iec958:CARD=Audio,DEV=0
    SA9227 USB Audio, USB Audio
    IEC958 (S/PDIF) Digital Audio Output


Jag tycker att iec958-enheten inte borde påverkas av volyminställningen på ljudenheten, till skillnad från hw, då den är till för att skicka AC3-ljudströmmar och sådant över S/PDIF men den påverkas likväl så det spelar ingen roll om jag väljer hw eller iec958 i praktiken (i det här fallet i alla fall) utan volymen måste sättas till 100% i alsamixer likväl (välj ljudenheten för SA9227 med F6).

Kod: Markera allt
#!/bin/bash

# can be another card number
if amixer -c 1 info | grep -q "HiFimeDIY SA9227 USB Audio"; then
    amixer -c 1 set PCM 100%
else
    echo "Didn't find HiFimeDIY SA9227 USB Audio to maximize volume."
fi

sox --no-dither --channels 2 --null --bits 16 test-sine.wav synth 2 sine 50 pad 3 4

in="hw:CARD=Audio,DEV=0"
out="hw:CARD=Audio,DEV=0"

aplay -v -D $out test-sine.wav &
sleep 1
arecord -v -D $in -c 2 -f S16_LE -r 48000 --duration=6 sample.wav
wait

./zeroed_offset_compare.py test-sine.wav sample.wav


Jag upptäckte att den senast uppspelade samplen låg kvar i ljudbufferten och spelades in när arecord borde spelat in 0:or. Om uppspelning av testfil påbörjas och avslutas under inspelning så får man dessutom lite skräp i början och slutet av det uppspelade ljudet vilket omöjliggör en enkel jämförelse av ljudmaterialet för att bedöma om återgivningen är bittrogen. Lösningen är att vända på det och spela upp ljud med tystnad i början och slutet längre tid än man spelar in.

Jag skrev ett program i Python för att jämföra ljudfilerna och det ignorerar inledande och avslutande tystnad (nollor, därav --no-dither för testfilen).

Kod: Markera allt
$ ./zeroed_offset_compare.py test-sine.wav sample.wav


Filtypen är inte tillåten att bifoga så här kommer programmet:
Kod: Markera allt
#!/usr/bin/env python3

"""
https://python-soundfile.readthedocs.io/
https://numpy.org/doc/stable/reference/arrays.ndarray.html
"""

import sys
import argparse
import numpy as np
import soundfile as sf

# type must be one of ['float32', 'float64', 'int16', 'int32']
SAMPLE_TYPE = "float32"

def read_snd(filename: str) -> tuple[np.ndarray, int]:
    """Takes filename, returns 2D array with samples and number of channels."""

    # 1D is just a list of samples, 2D is lists with a sample from each channel in a list.
    try:
        data, rate = sf.read(filename, dtype=SAMPLE_TYPE, always_2d=True)
    except sf.LibsndfileError as e:
        print(e)
        sys.exit(-1)

    # data.shape is a tuple with (samples, channels) when 2D
    print(f"{filename}:")
    print(f"\tsample rate = {rate}")
    print(f"\tnumber of channels = {data.shape[1]}")
    length = data.shape[0] / rate
    print(f"\tlength = {length}s ({data.shape[0]} samples per channel)")
    return data, data.data.shape[1]


def skip_zeroes(data: np.ndarray, index: int, channel: int) -> int:
    """Returns index for next non-zero sample."""
    length = data.shape[0]
    while index < length and data[index][channel] == 0:
        index += 1

    return index


def compare(frst: np.ndarray, scnd: np.ndarray, channel: int) -> int:
    """Compare a single audio channel in a 2D array of channels."""
    fi = 0
    si = 0

    # skip leading zeroes
    fi = skip_zeroes(frst, fi, channel)
    si = skip_zeroes(scnd, si, channel)

    flen = frst.shape[0]
    slen = scnd.shape[0]

    if fi == flen:
        print("First file is empty or zeroed.")
        return 1

    if si == slen:
        print("Second file is empty or zeroed.")
        return 1

    differences = 0

    while fi < flen and si < slen:
        if frst[fi][channel] != scnd[si][channel]:
            differences += 1
        fi += 1
        si += 1

    if differences > 0:
        print(f"Channel {channel} differ by at least {differences} samples.")
        return 1

    # skip trailing zeroes
    fi = skip_zeroes(frst, fi, channel)
    si = skip_zeroes(scnd, si, channel)

    if fi < flen or si < slen:
        print(f"Channel {channel} have different non-zeroed length.")
        return 1

    print(f"Channel {channel} are the same, ignoring zeroes at the beginning and the end.")
    return 0


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description="Comparing two sound files but ignoring leading and trailing zeroes.",
        epilog="Returns 0 if equal or number of channels that differ, -1 for error.")
    parser.add_argument("first", type=str, help="sound file")
    parser.add_argument("second", type=str, help="sound file to compare with")
    parser.add_argument("--channel", type=int, default=-1, help="single channel to compare, starting with 0")
    args = parser.parse_args()

    first, fch = read_snd(args.first)
    second, sch = read_snd(args.second)
    print("")

    if args.channel == -1 and fch != sch:
        print("Number of audio channels differ; select one with --channel.")
        sys.exit(-1)

    if args.channel != -1:
        if fch > args.channel and sch > args.channel:
            ret = compare(first, second, args.channel)
            sys.exit(ret)
        else:
            print("Invalid --channel number to compare.")
            sys.exit(-1)

    ret = 0
    for ch in range(fch):
        ret += compare(first, second, ch)

    if ret > 0:
        print("\nChecked volume settings?")

    sys.exit(ret)
Senast redigerad av pLudio 2024-09-24 09:36, redigerad totalt 4 gånger.
Caveat auditor. If bass was "faster" it would be "treble."

Neuhausen
 
Inlägg: 691
Blev medlem: 2023-07-12

Re: Bitperfekt Toslink loopback i Linux

Inläggav Neuhausen » 2024-09-16 13:28

Hatten av!

Det där är ett viktigt steg för att kunna verifiera andra ljudkällor också.

Tex hur olika datorer, ljudlager och operativsystem förändrar ljudet. För att inte tala om hur tex överföring mellan uppspelningsenhet och DAC förändrar ljudet. Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.

Användarvisningsbild
RogerGustavsson
 
Inlägg: 23582
Blev medlem: 2004-05-02
Ort: Huskvarna

Re: Bitperfekt Toslink loopback i Linux

Inläggav RogerGustavsson » 2024-09-16 13:58

Neuhausen skrev:Hatten av!

Det där är ett viktigt steg för att kunna verifiera andra ljudkällor också.

Tex hur olika datorer, ljudlager och operativsystem förändrar ljudet. För att inte tala om hur tex överföring mellan uppspelningsenhet och DAC förändrar ljudet. Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.


USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Användarvisningsbild
pLudio
 
Inlägg: 2753
Blev medlem: 2003-06-17
Ort: Stockholm

Re: Bitperfekt Toslink loopback i Linux

Inläggav pLudio » 2024-09-16 14:09

RogerGustavsson skrev:
Neuhausen skrev:Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.

USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Ljud över USB använder ofta isokron överföring som ger en garanterad bandbredd men ingen omsändning vid fel, till skillnad från vanlig dataöverföring över USB. Är kabeln halvkass så hörs det förstås också.
Caveat auditor. If bass was "faster" it would be "treble."

Användarvisningsbild
I-or
Herr Ekvalisator
 
Inlägg: 7774
Blev medlem: 2020-08-30

Re: Bitperfekt Toslink loopback i Linux

Inläggav I-or » 2024-09-16 14:48

Isokron överföring som används för USB Audio registrerar överföringsfel via CRC (Cyclic Redundancy Check), men korrigerar dem inte. Vissa enheter ignorerar felen medan andra deaktiverar utgången om felen blir för många.

Bitfel i audiosammanhang via USB-överföring är alltså förvisso teoretiskt möjligt, men i praktiken extremt ovanligt, då USB 2.0 är specificerat att ha en relativ felfrekvens om maximalt 10^-12. Kabeln måste alltså vara mer än halvkass, d.v.s. defekt, för att ge en felfrekvens överstigande ett fel per något eller några hundratal timmars lyssning.

Här finner man ett litet räkneexempel: viewtopic.php?p=2320119#p2320119
Teknisk konsult inom akustik och audioteknik

Användarvisningsbild
mn12
 
Inlägg: 542
Blev medlem: 2012-03-13
Ort: Stockholm

Re: Bitperfekt Toslink loopback i Linux

Inläggav mn12 » 2024-09-16 15:57

RogerGustavsson skrev:
Neuhausen skrev:Hatten av!

Det där är ett viktigt steg för att kunna verifiera andra ljudkällor också.

Tex hur olika datorer, ljudlager och operativsystem förändrar ljudet. För att inte tala om hur tex överföring mellan uppspelningsenhet och DAC förändrar ljudet. Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.


USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Det här är ju ett lysande sätt att visa kabeltroende att en kabel är bitperfekt (ska inte behövas). Det vore ju enkelt att visa med en diod i DACen om det blivit fel i överföringen (jämför klippindikator). Det skulle dämpa en hel del audio nervosa. Mitt gratistips till DACkonatruktörer.
Det här är ett stycke text som kan läggas till i inlägg du skapar. Det finns en gräns på 200 tecken.

jansch
 
Inlägg: 4047
Blev medlem: 2009-05-01

Re: Bitperfekt Toslink loopback i Linux

Inläggav jansch » 2024-09-16 16:02

pLudio skrev:
RogerGustavsson skrev:
Neuhausen skrev:Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.

USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Ljud över USB använder ofta isokron överföring som ger en garanterad bandbredd men ingen omsändning vid fel, till skillnad från vanlig dataöverföring över USB. Är kabeln halvkass så hörs det förstås också.


Alltså......
Slumpvis felaktig DIGITAL data förändrar inte ljudet på själva musiken. D v s "långsammare bas", "minskat djup", "svärta", "transparens", osv och andra audiofildefinitioner av ljudförändring kan ej ske. Ej heller "starkare bas", "krispigare diskant" etc.
Sannolikheten är i princip "noll". För att förändra signalen på ett "musikaliskt sätt" krävs att 16 bits skall få ett unikt/specifikt värde för varje enskilt sample, alltså miljontals bits måste påverkas/förändras perfekt.
Om man skall jämföra detta med något är det spelteori - man har då 65 536:dels chans att bitfelen bildar korrekt värde för varje sample som motsvarar den nya upplevda ljudupplevelsen.
Att 100 gånger vinna högsta vinsten på Lotto eller Triss är rena barnleken jämfört med detta.

Bitfel är oftast ohörbara eller så blir det knaster och andra oljud som inte följer musiken.
Kvantiseringsfel (avrundning/avrundningsfe)l kan i viss mån följa musiksignalen men det är en helt annan sak.

Jag tror det behövs en ny/specifik tråd i detta ämne då det är vanligt med "analogt tänk" om digitala signaler......

Användarvisningsbild
pLudio
 
Inlägg: 2753
Blev medlem: 2003-06-17
Ort: Stockholm

Re: Bitperfekt Toslink loopback i Linux

Inläggav pLudio » 2024-09-16 16:09

Ja, hörs bitfel så är det såklart oljud. Det är inga varsamt pålagda spatiala ljudeffekter eller något annat som inte skär i öronen när felen förekommer i större mängder. Eller så blir det tyst.

Med halvkass kabel menar jag brott eller glapp i kabeln. Det har aldrig varit ett praktiskt problem för mig och jag kommer inte ägna tid åt att testa kablar.
Caveat auditor. If bass was "faster" it would be "treble."

Neuhausen
 
Inlägg: 691
Blev medlem: 2023-07-12

Re: Bitperfekt Toslink loopback i Linux

Inläggav Neuhausen » 2024-09-16 17:52

pLudio skrev:
RogerGustavsson skrev:
Neuhausen skrev:Som att kunna verifiera att olika USB kablar inte förändrar ljudet när man använder det för att överföra ljudet mellan två enheter.

USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Ljud över USB använder ofta isokron överföring som ger en garanterad bandbredd men ingen omsändning vid fel, till skillnad från vanlig dataöverföring över USB. Är kabeln halvkass så hörs det förstås också.


Precis så, jag tycker att det skulle vara väldigt intressant att jämföra för att se om det ett problem eller audiofilsjuka. Det är också intressant för att felsöka system, datorer har hyss för sig som till stor del blir vårt ansvar när vi väljer en dator som uppspelare.

Jag tittade på hur det skulle vara möjligt att kontrollera med en Saleae logicanalysator. De har möjligheter för att avkoda i2s/pcm i sitt program. Men då jag saknar lite för mycket av de kunskaper som krävs så blir tröskeln lite högre än mitt intresse för ämnet.

I många fall så finns möjligheten att korrigera felet när man märker att den digitala signalen inte kommit fram som man tänkt. Tex om man spelar upp en musikfil från en server via nätverket. Försvinner det paket så har man en ganska lång buffer att spela upp från innan första felet hörs och inget skiljer ljuddata som skickas från data där en ändrad bit leder till katastrofal dataförlust, så all data kommer fram oskadd. Den långa buffern gör att det finns gott om tid att få fram all data i gott skick även på en ganska rutten wifi anslutning. Hur mycket felkorrektion olika streaminglösningar har vågar jag inte gissa om.

En snabb sökning på USB Audio Class 1.0 och 2.0 verkar helt sakna en metod för felkorrektion. Dvs inte USB 1.0 eller USB 2.0, UAC 1.0 eller UAC 2.0 är mer korrekt. Så om man inte behöver en drivrutin för sitt ljudkort/ljudinterace/DAC så kan man räkna med att det inte finns någon felkorrektion. Det finns feldetektion, men inget sätt att korrigera felet. Precis som med SPDIF och Toslink.

Inget hindrar att USB används för att skicka ljud med felkorrektion med mycket lite fördröjning då även USB 1.0 med 12Mbit överföringshastighet kan skicka ljud åtta gånger snabbare än vad som krävs för en vanlig CD. Men då skulle det vara svårare att få saker att fungera tillsammans än det är nu med den ganska oambitiösa UAC 1.0 och 2.0 standarden som alla verkar använda.

Men det är som sagt trevligt att kunna verifiera olika överföringar.

Användarvisningsbild
pLudio
 
Inlägg: 2753
Blev medlem: 2003-06-17
Ort: Stockholm

Re: Bitperfekt Toslink loopback i Linux

Inläggav pLudio » 2024-09-16 18:28

Neuhausen skrev:Hur mycket felkorrektion olika streaminglösningar har vågar jag inte gissa om.

Det brukar vara webbförfrågningar över TCP/IP (som skickar om trasiga paket) så man behöver inte tänka på det. Ljudfilerna har i sin tur CRC för att upptäcka fel under strömning och åtminstone FLAC har även en MD5 hash för hela ljudströmmen i filen för lokal verifiering av innehållet.

Kod: Markera allt
flac --test example.flac


Det är ett löst problem.
Caveat auditor. If bass was "faster" it would be "treble."

Användarvisningsbild
dewpo
 
Inlägg: 5582
Blev medlem: 2016-08-01

Re: Bitperfekt Toslink loopback i Linux

Inläggav dewpo » 2024-09-16 19:04

jansch skrev:
pLudio skrev:
RogerGustavsson skrev:USB-kabeln kan väl inte förändra ljudet? Det som stoppas in kommer ut i andra änden.

Ljud över USB använder ofta isokron överföring som ger en garanterad bandbredd men ingen omsändning vid fel, till skillnad från vanlig dataöverföring över USB. Är kabeln halvkass så hörs det förstås också.


Alltså......
Slumpvis felaktig DIGITAL data förändrar inte ljudet på själva musiken. D v s "långsammare bas", "minskat djup", "svärta", "transparens", osv och andra audiofildefinitioner av ljudförändring kan ej ske. Ej heller "starkare bas", "krispigare diskant" etc.
Sannolikheten är i princip "noll". För att förändra signalen på ett "musikaliskt sätt" krävs att 16 bits skall få ett unikt/specifikt värde för varje enskilt sample, alltså miljontals bits måste påverkas/förändras perfekt.
Om man skall jämföra detta med något är det spelteori - man har då 65 536:dels chans att bitfelen bildar korrekt värde för varje sample som motsvarar den nya upplevda ljudupplevelsen.
Att 100 gånger vinna högsta vinsten på Lotto eller Triss är rena barnleken jämfört med detta.

Bitfel är oftast ohörbara eller så blir det knaster och andra oljud som inte följer musiken.
Kvantiseringsfel (avrundning/avrundningsfe)l kan i viss mån följa musiksignalen men det är en helt annan sak.

Jag tror det behövs en ny/specifik tråd i detta ämne då det är vanligt med "analogt tänk" om digitala signaler......


Jag hade problem med optisk Toslink överföring från min dator till min receiver :| Den spelade som den skulle ett par sekunder sen snabbade ljudet upp en kort stund (tänk pitch) sen normalt ett par sekunder och det hela upprepade sig cykliskt. Lät helt enkelt förfärligt. Jag gissar att det berodde på att datorn avvek för mycket från giltig klockhastighet så att receivern inte kunde låsa riktigt på signalen? Men det lätt faktiskt ganska analogt som svaj på en lp ungefär...
Framtiden är här... men har den blivit som vi önskade den?
Läs innan du beaktar Disclaimer-> Viktig information

Användarvisningsbild
pLudio
 
Inlägg: 2753
Blev medlem: 2003-06-17
Ort: Stockholm

Re: Bitperfekt Toslink loopback i Linux

Inläggav pLudio » 2024-09-16 19:52

dewpo skrev:Jag hade problem med optisk Toslink överföring från min dator till min receiver :| Den spelade som den skulle ett par sekunder sen snabbade ljudet upp en kort stund (tänk pitch) sen normalt ett par sekunder och det hela upprepade sig cykliskt. Lät helt enkelt förfärligt. Jag gissar att det berodde på att datorn avvek för mycket från giltig klockhastighet så att receivern inte kunde låsa riktigt på signalen? Men det lätt faktiskt ganska analogt som svaj på en lp ungefär...

Där hade det varit intressant med ett jittertest. Hittas i REW Generator -> Tones -> J-test och så pre-out in i RTA med linjär skala.
Caveat auditor. If bass was "faster" it would be "treble."

jansch
 
Inlägg: 4047
Blev medlem: 2009-05-01

Re: Bitperfekt Toslink loopback i Linux

Inläggav jansch » 2024-09-16 21:22

dewpo skrev:
jansch skrev:
pLudio skrev:Ljud över USB använder ofta isokron överföring som ger en garanterad bandbredd men ingen omsändning vid fel, till skillnad från vanlig dataöverföring över USB. Är kabeln halvkass så hörs det förstås också.


Alltså......
Slumpvis felaktig DIGITAL data förändrar inte ljudet på själva musiken. D v s "långsammare bas", "minskat djup", "svärta", "transparens", osv och andra audiofildefinitioner av ljudförändring kan ej ske. Ej heller "starkare bas", "krispigare diskant" etc.
Sannolikheten är i princip "noll". För att förändra signalen på ett "musikaliskt sätt" krävs att 16 bits skall få ett unikt/specifikt värde för varje enskilt sample, alltså miljontals bits måste påverkas/förändras perfekt.
Om man skall jämföra detta med något är det spelteori - man har då 65 536:dels chans att bitfelen bildar korrekt värde för varje sample som motsvarar den nya upplevda ljudupplevelsen.
Att 100 gånger vinna högsta vinsten på Lotto eller Triss är rena barnleken jämfört med detta.

Bitfel är oftast ohörbara eller så blir det knaster och andra oljud som inte följer musiken.
Kvantiseringsfel (avrundning/avrundningsfe)l kan i viss mån följa musiksignalen men det är en helt annan sak.

Jag tror det behövs en ny/specifik tråd i detta ämne då det är vanligt med "analogt tänk" om digitala signaler......


Jag hade problem med optisk Toslink överföring från min dator till min receiver :| Den spelade som den skulle ett par sekunder sen snabbade ljudet upp en kort stund (tänk pitch) sen normalt ett par sekunder och det hela upprepade sig cykliskt. Lät helt enkelt förfärligt. Jag gissar att det berodde på att datorn avvek för mycket från giltig klockhastighet så att receivern inte kunde låsa riktigt på signalen? Men det lätt faktiskt ganska analogt som svaj på en lp ungefär...


Digitalt "ljud" (bitströmmar) liksom all annan digital data är diskontinuerlig. Därför måste man ange vid vilken hastighet datat måste läsas.
Man kan säga att i den logiska världen finns inte tid definierad, eller statuslägena "1" och "0" är tidslösa.
Därför har en processor en "klocka", liksom diskdrivers, osv. för att tillföra tid som just då behövs
För en ljudfil förändras "hastigheten" beroende på hur olika kretslösningar är designade, Man växlar mellan parallell och seriell hantering, man buffrar upp data, man tillför data (t.ex CRC, synk bits,).

Vid t.ex CD och USB är sådär 75% "musikbits" och dessutom fördelade på 2 kanaler (stereo), resten är overhead till för fekorrigering, synkning etc.
De samples som vi till slut vill avläsa har alltså en synnerligen varierande hastighet, som ett 24 timmars lopp på LeMans.
Hastigheten spelar ingen roll så länge den totala bitrate:n inte uderstiger D/Aomvandlarens behov.
Först när vi taktar ut en analog avläsning tillför vi korrekt tid i form av t.ex 48k samples/sekund.
Den informationen, vid vilken hastighet analoga värden skall avläsas, har datafilen innehållit som en "overhead".

Så vår riktiga "tid" finns bara i analoga världen, i digitala världen finns bara en binär spec på hastigheten.

Lite förenklat.......


Återgå till DIY-forum


Vilka är online

Användare som besöker denna kategori: Bing [Bot] och 236 gäster